Find ve sed kullanarak dosyaları yinelemeli olarak yeniden adlandırın


87

Bir grup dizini gözden geçirmek ve _test.rb ile biten tüm dosyaları bunun yerine _spec.rb ile bitecek şekilde yeniden adlandırmak istiyorum. Bu, bash ile nasıl yapılacağını asla tam olarak anlayamadığım bir şey, bu yüzden bu sefer çivilenmesi için biraz çaba sarf edeceğimi düşündüm. Şimdiye kadar yetersiz kaldım, en iyi çabam:

find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \;

Not: exec'den sonra fazladan bir yankı var, böylece ben test ederken komut çalıştırılmak yerine yazdırılır.

Çalıştırdığımda, eşleşen her dosya adı için çıktı:

mv original original

yani sed ile ikame kaybolmuştur. Hilesi ne?


BTW, bir yeniden adlandırma komutu olduğunun farkındayım, ancak gelecekte daha güçlü komutlar yapabilmek için sed kullanarak nasıl yapılacağını gerçekten öğrenmek isterim.
opsb

2
Lütfen çapraz gönderi yapmayın .
Dennis Williamson

Yanıtlar:


32

Bunun nedeni , aşağıdakilerle doğrulanabildiği gibi seddizeyi {}girdi olarak almasıdır:

find . -exec echo `echo "{}" | sed 's/./foo/g'` \;

foofoodizindeki her dosya için özyinelemeli olarak yazdırır . Bu davranışın nedeni, boru hattının tüm komutu genişlettiğinde kabuk tarafından bir kez yürütülmesidir.

İşlem sedhattını findher dosya için çalıştıracak şekilde alıntı yapmanın bir yolu findyoktur , çünkü kabuk aracılığıyla komutları yürütmez ve ardışık düzen veya geri alıntılar kavramı yoktur. GNU findutils el kitabı, ardışık düzenini ayrı bir kabuk betiğine koyarak benzer bir görevin nasıl gerçekleştirileceğini açıklar:

#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'

( sh -cTüm bunları tek bir komutta kullanmanın bazı sapkın yolları ve tonlarca alıntı olabilir, ama denemeyeceğim.)


27
Sh -c'nin sapkın kullanımını merak edenler için burada: spec -name "* _test.rb" -exec sh -c 'echo mv "$ 1" "$ (echo" $ 1 "| sed s / test.rb bulun \ $ / spec.rb /) "'_ {} \;
opsb

1
@opsb bu ne için _ için? harika çözüm - ama ramtam yanıtını daha çok seviyorum :)
iRaS

Şerefe! Beni çok fazla baş ağrısından kurtardı. Bütünlük uğruna, onu bir betiğe şu şekilde aktarıyorum: bul. -name "dosya" -exec sh /path/to/script.sh {} \;
Sven M.

131

Bunu orijinal soruna en yakın şekilde çözmek için muhtemelen xargs "komut satırı başına args" seçeneğini kullanmak olacaktır:

find . -name "*_test.rb" | sed -e "p;s/test/spec/" | xargs -n2 mv

Geçerli çalışma dizinindeki dosyaları özyinelemeli olarak bulur, orijinal dosya adını ( p) ve sonra değiştirilmiş adı ( s/test/spec/) yansıtır ve hepsini mvçiftler halinde ( xargs -n2) besler . Bu durumda yolun kendisinin bir dize içermemesi gerektiğine dikkat edin test.


9
Ne yazık ki bunda beyaz boşluk sorunları var. Bu nedenle, adında boşluklar olan klasörlerle kullanmak, onu
xargs'de bozar

1
Tam olarak aradığım buydu. Beyaz boşluk sorunu için çok kötü (yine de test etmedim). Ancak mevcut ihtiyaçlarım için mükemmel. Önce "xargs" parametresinde "mv" yerine "echo" ile test etmenizi öneririm.
Michele Dall'Agata

5
-z-print0-0find -name '*._test.rb' -print0 | sed -ze "p;s/test/spec/" | xargs -0 -n2 mv
Yollardaki boşluklarla uğraşmanız gerekiyorsa

En iyi çözüm. -Exec bulmaktan çok daha hızlı. Teşekkür ederim
Miguel A. Baldi Hörlle

testBir yolda birden fazla klasör varsa bu işe yaramaz . sedyalnızca ilkini yeniden adlandırır ve mvkomut No such file or directoryhata durumunda başarısız olur .
Casey

22

başka şekilde düşünmek isteyebilirsin

for file in $(find . -name "*_test.rb")
do 
  echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`
done

Bunu yapmanın iyi bir yolu gibi görünüyor. Bilgimi her şeyden daha fazla geliştirmek için, gerçekten tek çizgiyi kırmaya çalışıyorum.
opsb

2
$ (. -name "* _test.rb" bulun) içindeki dosya için; echo mv $ dosya yapmak echo $file | sed s/_test.rb$/_spec.rb/; yapılan tek satırlık değil mi?
Bretticus

5
Boşluk içeren dosya adlarınız varsa bu çalışmayacaktır. foronları ayrı kelimelere ayıracak. For döngüsüne yalnızca satırsonu satırlarına bölme talimatı vererek çalışmasını sağlayabilirsiniz. Örnekler için cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html sayfasına bakın .
2014

-execBul seçeneğinden kullanmayı tercih etsem de @onitake'ye katılıyorum .
ShellFish

18

Bunu daha kısa buluyorum

find . -name '*_test.rb' -exec bash -c 'echo mv $0 ${0/test.rb/spec.rb}' {} \;

Merhaba, sanırım ' _test.rb' ' _test.rb' olmalı (tek tırnak için çift tırnak). Bana find . -name '*_test.rb' -exec bash -c 'echo mv $0 ${0/test.rb/spec.rb}' {} \;çalışıyor gibi göründüğünde $ 1'i konumlandırmak istediğiniz argümanı itmek için neden alt çizgiyi kullandığınızı sorabilir miyim find . -name '*_test.rb' -exec bash -c 'echo mv $1 ${1/test.rb/spec.rb}' iAmArgumentZero {} \;
Olacağı

Önerileriniz için teşekkürler, düzeltildi
csg


9

İsterseniz sed olmadan yapabilirsiniz:

for i in `find -name '*_test.rb'` ; do mv $i ${i%%_test.rb}_spec.rb ; done

${var%%suffix}suffixdeğerinden şeritler var.

veya sed kullanarak yapmak için:

for i in `find -name '*_test.rb'` ; do mv $i `echo $i | sed 's/test/spec/'` ; done

bu sed, kabul edilen cevapla açıklandığı gibi ( biri) çalışmıyor .
Ali

@Ali, işe yarıyor - cevabı yazarken kendim test ettim. @ larsman açıklaması için geçerli değildir for i in... ; do ... ; donekabuk üzerinden komutlar çalıştırır ve hangi gelmez backtick anlıyoruz.
Wayne Conrad

9

bashKabuğunuz olarak kullandığınızı söylüyorsunuz , bu durumda aslında ihtiyacınız yok findve sedpeşinde olduğunuz toplu yeniden adlandırmayı elde etmek için ...

bashKabuğunuz olarak kullandığınızı varsayarsak :

$ echo $SHELL
/bin/bash
$ _

... ve sözde globstarkabuk seçeneğini etkinleştirdiğinizi varsayarsak :

$ shopt -p globstar
shopt -s globstar
$ _

... ve son olarak renameyardımcı programı yüklediğinizi varsayarsak ( util-linux-ngpakette bulunur)

$ which rename
/usr/bin/rename
$ _

... daha sonra toplu yeniden adlandırmayı bir bash tek satırda aşağıdaki gibi elde edebilirsiniz :

$ rename _test _spec **/*_test.rb

( globstarkabuk seçeneği *_test.rb, dizin hiyerarşisine ne kadar derinlemesine yerleştirilmiş olurlarsa olsunlar, bash'nin eşleşen tüm dosyaları help shoptbulmasını sağlar ... seçeneğin nasıl ayarlanacağını öğrenmek için kullanın)


7

En kolay yol :

find . -name "*_test.rb" | xargs rename s/_test/_spec/

En hızlı yol (4 işlemciniz olduğunu varsayarak):

find . -name "*_test.rb" | xargs -P 4 rename s/_test/_spec/

İşlenecek çok sayıda dosyanız varsa, xargs'a iletilen dosya adları listesinin elde edilen komut satırının izin verilen maksimum uzunluğu aşmasına neden olması mümkündür.

Sisteminizin limitini kullanarak kontrol edebilirsiniz. getconf ARG_MAX

Çoğu linux sisteminde, ne kadar RAM ile çalışmanız gerektiğini bulmak için kullanabilir free -bveya cat /proc/meminfobulabilirsiniz; Aksi takdirde, topveya sistem etkinlik izleme uygulamasını kullanın.

Daha güvenli bir yol (çalışmak için 1000000 bayt RAM'iniz olduğunu varsayarsak):

find . -name "*_test.rb" | xargs -s 1000000 rename s/_test/_spec/

2

Dosya adlarında boşluklar olduğunda benim için işe yarayan şey buydu. Aşağıdaki örnek, tüm .dar dosyalarını özyinelemeli olarak .zip dosyalarına yeniden adlandırır:

find . -name "*.dar" -exec bash -c 'mv "$0" "`echo \"$0\" | sed s/.dar/.zip/`"' {} \;

2

Bunun için ihtiyacınız yok sed. Bir süreç ikamesiwhile sonucu beslenen bir döngü ile mükemmel bir şekilde yalnız kalabilirsiniz .find

Dolayısıyla find, gerekli dosyaları seçen bir ifadeniz varsa , sözdizimini kullanın:

while IFS= read -r file; do
     echo "mv $file ${file%_test.rb}_spec.rb"  # remove "echo" when OK!
done < <(find -name "*_test.rb")

Bu find, dizeyi _test.rben sondan çıkararak ve sona ekleyerek hepsini dosyalayacak ve yeniden adlandıracaktır _spec.rb.

Bu adım için kullandığımız Kabuk Parametrelerinin${var%string} gelen kısa eşleşme kalıbı "dizesini" kaldırır $var.

$ file="HELLOa_test.rbBYE_test.rb"
$ echo "${file%_test.rb}"          # remove _test.rb from the end
HELLOa_test.rbBYE
$ echo "${file%_test.rb}_spec.rb"  # remove _test.rb and append _spec.rb
HELLOa_test.rbBYE_spec.rb

Bir örneğe bakın:

$ tree
.
├── ab_testArb
├── a_test.rb
├── a_test.rb_test.rb
├── b_test.rb
├── c_test.hello
├── c_test.rb
└── mydir
    └── d_test.rb

$ while IFS= read -r file; do echo "mv $file ${file/_test.rb/_spec.rb}"; done < <(find -name "*_test.rb")
mv ./b_test.rb ./b_spec.rb
mv ./mydir/d_test.rb ./mydir/d_spec.rb
mv ./a_test.rb ./a_spec.rb
mv ./c_test.rb ./c_spec.rb

Çok teşekkürler! Tüm dosya adlarından özyinelemeli olarak takip eden .gz'yi kolayca kaldırmama yardımcı oldu. while IFS= read -r file; do mv $file ${file%.gz}; done < <(find -type f -name "*.gz")
Vinay Vissh

1
@CasualCoder bunu okumak güzel :) Doğrudan söyleyebileceğinizi unutmayın find .... -exec mv .... Ayrıca, $fileboşluk içeriyorsa başarısız olacağı için dikkatli olun . Alıntıları daha iyi kullanın "$file".
fedorqui

1

Ruby'niz varsa (1.9+)

ruby -e 'Dir["**/*._test.rb"].each{|x|test(?f,x) and File.rename(x,x.gsub(/_test/,"_spec") ) }'

1

Ramtam'ın beğendiğim cevabında, bul kısmı iyi çalışıyor, ancak yolda boşluklar varsa geri kalanı çalışmıyor. Sed'e çok aşina değilim, ancak bu cevabı şu şekilde değiştirebildim:

find . -name "*_test.rb" | perl -pe 's/^((.*_)test.rb)$/"\1" "\2spec.rb"/' | xargs -n2 mv

Gerçekten böyle bir değişikliğe ihtiyacım vardı çünkü benim kullanım durumumda son komut daha çok

find . -name "olddir" | perl -pe 's/^((.*)olddir)$/"\1" "\2new directory"/' | xargs -n2 mv

1

Her şeyi yeniden yapacak yüreğim yok ama bunu Commandline Find Sed Exec'e cevabım olarak yazdım . Orada soruyu soran kişi, muhtemelen bir veya iki dizini hariç tutarak bir ağacın tamamını nasıl taşıyacağını ve "OLD" dizesini içeren tüm dosya ve dizinleri "NEW" içerecek şekilde yeniden adlandırmayı istedi .

Aşağıdaki özenli ayrıntılarla nasıl anlatılacağını açıklamanın yanı sıra , bu yöntem yerleşik hata ayıklamayı içerdiği için de benzersiz olabilir. Temelde, istenen işi gerçekleştirmek için yapması gerektiğine inandığı tüm komutları derlemek ve bir değişkene kaydetmek dışında hiçbir şey yazmaz.

Ayrıca , döngüleri olabildiğince açık bir şekilde önler . Ayrıca sedbirden fazla maç için özyinelemeli arama deseni bildiğim kadarıyla olarak başka Yinelemesiz yoktur.

Ve son olarak, bu tamamen nullsınırlandırılmıştır - herhangi bir dosya adında null. Buna sahip olman gerektiğini düşünmüyorum.

Bu arada, bu GERÇEKTEN hızlı. Bak:

% _mvnfind() { mv -n "${1}" "${2}" && cd "${2}"
> read -r SED <<SED
> :;s|${3}\(.*/[^/]*${5}\)|${4}\1|;t;:;s|\(${5}.*\)${3}|\1${4}|;t;s|^[0-9]*[\t]\(mv.*\)${5}|\1|p
> SED
> find . -name "*${3}*" -printf "%d\tmv %P ${5} %P\000" |
> sort -zg | sed -nz ${SED} | read -r ${6}
> echo <<EOF
> Prepared commands saved in variable: ${6}
> To view do: printf ${6} | tr "\000" "\n"
> To run do: sh <<EORUN
> $(printf ${6} | tr "\000" "\n")
> EORUN
> EOF
> }
% rm -rf "${UNNECESSARY:=/any/dirs/you/dont/want/moved}"
% time ( _mvnfind ${SRC=./test_tree} ${TGT=./mv_tree} \
> ${OLD=google} ${NEW=replacement_word} ${sed_sep=SsEeDd} \
> ${sh_io:=sh_io} ; printf %b\\000 "${sh_io}" | tr "\000" "\n" \
> | wc - ; echo ${sh_io} | tr "\000" "\n" |  tail -n 2 )

   <actual process time used:>
    0.06s user 0.03s system 106% cpu 0.090 total

   <output from wc:>

    Lines  Words  Bytes
    115     362   20691 -

    <output from tail:>

    mv .config/replacement_word-chrome-beta/Default/.../googlestars \
    .config/replacement_word-chrome-beta/Default/.../replacement_wordstars        

NOT: Yukarıdakiler functionbüyük olasılıkla ve ve çağrılarının düzgün şekilde GNUişlenmesi için sedve sürümlerini gerektirecektir . Bunlar sizin için mevcut değilse, işlevsellik birkaç küçük ayarlamayla büyük olasılıkla kopyalanabilir.findfind printfsed -z -e:;recursive regex test;t

Bu, baştan sona istediğiniz her şeyi çok az telaşla yapmalıdır. Yaptığım forkile sed, ama aynı zamanda bazı pratik yapıyordum sedben bu yüzden buradayım yıllardan bu kadar özyinelemeli dallanma teknikleri. Bir berber okulunda indirimli saç kesimi yapmak gibi sanırım. İşte iş akışı:

  • rm -rf ${UNNECESSARY}
    • Her türlü veriyi silebilecek veya yok edebilecek herhangi bir işlevsel çağrıyı kasıtlı olarak dışarıda bıraktım. Bunun ./appistenmeyen olabileceğini söylüyorsunuz. Önceden silin veya başka bir yere taşıyın ya da alternatif olarak bunu programlı olarak yapmak için bir \( -path PATTERN -exec rm -rf \{\} \)rutin oluşturabilirsiniz find, ancak bu tamamen sizin.
  • _mvnfind "${@}"
    • Argümanlarını bildirin ve worker (işçi) işlevini çağırın. ${sh_io}işlevin getirisini kaydetmesi açısından özellikle önemlidir. ${sed_sep}yakın bir saniyede gelir; bu, sedişlevdeki özyinelemesine başvurmak için kullanılan rastgele bir dizedir . Eğer ${sed_sep}potansiyel olarak Path- veya üzerine ... iyi, sadece olmasına izin verme davrandı dosya adlarından herhangi bulunabilir olabilecek bir değere ayarlanır.
  • mv -n $1 $2
    • Ağacın tamamı baştan taşınır. Çok fazla baş ağrısını kurtaracak; inan bana. Yapmak istediklerinizin geri kalanı - yeniden adlandırma - sadece bir dosya sistemi meta verisi meselesidir. Örneğin, bunu bir sürücüden diğerine veya herhangi bir dosya sistemi sınırının ötesine taşıyorsanız, bunu tek bir komutla yapmanız daha iyi olur. Aynı zamanda daha güvenlidir. Aşağıdakiler için -noclobberayarlanan seçeneğe dikkat edin mv; yazıldığı gibi, bu işlev zaten var olan ${SRC_DIR}yere koymayacaktır ${TGT_DIR}.
  • read -R SED <<HEREDOC
    • Kaçan güçlüklerden tasarruf etmek için tüm sed komutlarını burada buldum ve aşağıda sed'i beslemek için bunları bir değişkene okudum. Aşağıdaki açıklama.
  • find . -name ${OLD} -printf
    • Biz başlamak findsüreci. İle findsadece yeniden adlandırılması gereken herhangi bir şeyi ararız çünkü tüm yer-yer mvişlemleri fonksiyonun ilk komutuyla zaten yaptık . Örneğin findbir execçağrı gibi herhangi bir doğrudan eylemde bulunmak yerine, komut satırını dinamik olarak oluşturmak için kullanırız -printf.
  • %dir-depth :tab: 'mv '%path-to-${SRC}' '${sed_sep}'%path-again :null delimiter:'
    • findİhtiyacımız olan dosyaları bulduktan sonra , doğrudan yeniden adlandırmanızı işlememiz gereken komutun ( çoğunu ) oluşturur ve yazdırır . %dir-depthHer satırın başlangıcı henüz yeniden adlandırılması olduğu üst nesneyle ağacında bir dosya veya dizini yeniden adlandırmak için çalışmıyoruz sağlamaya yardımcı olur tacked. finddosya sistemi ağacınızda gezinmek için her türlü optimizasyon tekniğini kullanır ve ihtiyacımız olan verileri işlemler için güvenli bir sırada döndüreceği kesin değildir. Bu yüzden sıradaki ...
  • sort -general-numerical -zero-delimited
    • $ {SRC} ile ilişkide en yakın yollar önce çalışılacak şekilde tüm findçıktılarını %directory-depthsıralarız. Bu mv, dosyaların var olmayan konumlara dahil edilmesiyle ilgili olası hataları önler ve yinelemeli döngü ihtiyacını en aza indirir. ( aslında, bir döngü bulmakta zorlanabilirsiniz )
  • sed -ex :rcrs;srch|(save${sep}*til)${OLD}|\saved${SUBSTNEW}|;til ${OLD=0}
    • Bence bu, tüm komut dosyasındaki tek döngü ve %Pathdeğiştirilmesi gerekebilecek birden fazla $ {OLD} değeri içermesi durumunda, her dizge için yazdırılan ikinci döngüde yalnızca döngü oluyor . Hayal ettiğim tüm diğer çözümler ikinci bir sedsüreci içeriyordu ve kısa bir döngü arzu edilmeyebilirken, kesinlikle tüm bir sürecin ortaya çıkmasını ve çatallanmasını yener.
    • Yani temelde sedburada yapılan, $ {sed_sep} için arama yapmaktır, o zaman, onu bulduktan sonra, onu ve karşılaştığı tüm karakterleri $ {OLD} bulana kadar kaydeder, sonra onu $ {NEW} ile değiştirir. Daha sonra $ {sed_sep} 'e geri döner ve dizede birden fazla olması durumunda $ {OLD} için tekrar arar. Bulunmazsa, değiştirilen dizeyi yazdırır stdout(daha sonra tekrar yakalar) ve döngüyü sona erdirir.
    • Bu, tüm dizeyi ayrıştırma zorunluluğunu ortadan kaldırır ve mvelbette $ {OLD} içermesi gereken komut dizesinin ilk yarısının bunu içermesini ve ikinci yarısının da silmek için gerektiği kadar değiştirilmesini sağlar. mvHedef yolundan $ {OLD} adı .
  • sed -ex...-ex search|%dir_depth(save*)${sed_sep}|(only_saved)|out
    • Buradaki iki -execçağrı bir saniye olmadan gerçekleşir fork. İlkinde, gördüğümüz mvgibi , $ {OLD} ile $ {NEW} arasındaki tüm referansları düzgün bir şekilde değiştirmek için find's -printffunction komutunun sağladığı komutu gerektiği gibi değiştirdik, ancak bunu yapmak için bazılarını kullanmalıydık nihai çıktıya dahil edilmemesi gereken keyfi referans noktaları. Yani sedyapması gereken her şeyi bitirdiğinde, ona geçmeden önce bekleme tamponundaki referans noktalarını silmesi talimatını veriyoruz.

VE ŞİMDİ ETRAFTAYIZ

read şuna benzer bir komut alacak:

% mv /path2/$SRC/$OLD_DIR/$OLD_FILE /same/path_w/$NEW_DIR/$NEW_FILE \000

Olacak readiçine ${msg}olarak ${sh_io}işlev irade dışarıdan muayene edilebileceği.

Güzel.

-Mike


1

Onitake'nin önerdiği örnekleri takip ederek boşluklu dosya adlarını işleyebildim .

Bu vermez yolu boşluk veya dize içeriyorsa kırmak test:

find . -name "*_test.rb" -print0 | while read -d $'\0' file
do
    echo mv "$file" "$(echo $file | sed s/test/spec/)"
done

1

Bu, her durumda çalışması gereken bir örnektir. Yinelemeli çalışır, Yalnızca kabuk gerekir ve boşluklu dosya adlarını destekler.

find spec -name "*_test.rb" -print0 | while read -d $'\0' file; do mv "$file" "`echo $file | sed s/test/spec/`"; done

0
$ find spec -name "*_test.rb"
spec/dir2/a_test.rb
spec/dir1/a_test.rb

$ find spec -name "*_test.rb" | xargs -n 1 /usr/bin/perl -e '($new=$ARGV[0]) =~ s/test/spec/; system(qq(mv),qq(-v), $ARGV[0], $new);'
`spec/dir2/a_test.rb' -> `spec/dir2/a_spec.rb'
`spec/dir1/a_test.rb' -> `spec/dir1/a_spec.rb'

$ find spec -name "*_spec.rb"
spec/dir2/b_spec.rb
spec/dir2/a_spec.rb
spec/dir1/a_spec.rb
spec/dir1/c_spec.rb

Ah .. sed'i mantığı bir kabuk betiğine koymak ve onu exec'de çağırmaktan başka bir yol bilmiyorum. başlangıçta sed kullanma gereksinimini görmedim
Damodharan R

0

Sorunuz sed ile ilgili gibi görünüyor, ancak yinelemeli yeniden adlandırma hedefinize ulaşmak için, burada verdiğim başka bir yanıttan utanmazca koparılmış olarak şunu öneririm: bash'da yinelemeli yeniden adlandırma

#!/bin/bash
IFS=$'\n'
function RecurseDirs
{
for f in "$@"
do
  newf=echo "${f}" | sed -e 's/^(.*_)test.rb$/\1spec.rb/g'
    echo "${f}" "${newf}"
    mv "${f}" "${newf}"
    f="${newf}"
  if [[ -d "${f}" ]]; then
    cd "${f}"
    RecurseDirs $(ls -1 ".")
  fi
done
cd ..
}
RecurseDirs .

Seçeneği ayarlamazsanız, sedkaçmadan nasıl çalışır ? ()-r
mikeserv

0

Find utils ve sed normal ifade türü ile yeniden adlandırma yapmanın daha güvenli yolu:

  mkdir ~/practice

  cd ~/practice

  touch classic.txt.txt

  touch folk.txt.txt

".Txt.txt" uzantısını aşağıdaki gibi kaldırın -

  cd ~/practice

  find . -name "*txt" -execdir sh -c 'mv "$0" `echo "$0" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//'`' {} \;

+ Yerine; toplu modda çalışmak için, yukarıdaki komut yalnızca ilk eşleşen dosyayı yeniden adlandırır, ancak dosya eşleşmelerinin tamamını 'bul' ile yeniden adlandırmaz.

  find . -name "*txt" -execdir sh -c 'mv "$0" `echo "$0" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//'`' {} +

0

İşte hile yapan güzel bir oneliner. Sed bu hakkın üstesinden gelemez, özellikle xargs tarafından -n 2 ile birden çok değişken geçirilirse.

find ./spec -type f -name "*_test.rb" -print0 | xargs -0 -I {} sh -c 'export file={}; mv $file ${file/_test.rb/_spec.rb}'

-Type -f eklenmesi taşıma işlemlerini yalnızca dosyalarla sınırlandırır, -print 0 ise yollardaki boş alanları ele alır.



0

Bu benim çalışma çözümüm:

for FILE in {{FILE_PATTERN}}; do echo ${FILE} | mv ${FILE} $(sed 's/{{SOURCE_PATTERN}}/{{TARGET_PATTERN}}/g'); done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.