Yanıtlar:
Taşınabilir bir yol (POSIX uyumlu herhangi bir sistemde çalışacak):
find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;
Bash4'te, özyinelemeli globları almak için globstar kullanabilirsiniz (**):
shopt -s globstar
for file in /the/path/**/*.abc; do
mv "$file" "${file%.abc}.edefg"
done
renameUbuntu'daki (perl) komutu, globstar veya ile birleştirebileceğiniz perl normal ifade sözdizimini kullanarak dosyaları yeniden adlandırabilir find:
# Using globstar
shopt -s globstar
files=(/the/path/**/*.abc)
# Best to process the files in chunks to avoid exceeding the maximum argument
# length. 100 at a time is probably good enough.
# See http://mywiki.wooledge.org/BashFAQ/095
for ((i = 0; i < ${#files[@]}; i += 100)); do
rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
done
# Using find:
find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +
Ayrıca bkz. Http://mywiki.wooledge.org/BashFAQ/030
${1%.abc}...
sh -c ilk argüman $ 0'a atanır ve kalan argümanlar konumsal parametrelere atanır . Yani bu _kukla bir argümandır ve '{}' ilk konum argümanıdır sh -c.
Tüm dosyalar aynı klasördeyse, bu işlem gerekli görevi yerine getirecektir.
rename 's/.abc$/.edefg/' *.abc
Dosyaları sürekli olarak yeniden adlandırmak için şunu kullanın:
find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'
rename 's/.abc$/.edefg/' /path/to/root/folder/**/*.abcBash'in modern bir versiyonunda.
s, başlangıçtakiler ve orada başka hangi seçenekleri kullanabilirim. Teşekkürler !
Özyinelemeli yeniden adlandırmalarla ilgili bir sorun, dosyaları bulmak için hangi yöntemi kullanırsanız kullanın rename, yalnızca dosya adını değil tüm yolu geçmesidir. Bu, iç içe klasörlerdeki karmaşık adların yapılmasını zorlaştırır.
Kullandığım find'ın -execdirbu sorunu çözmek için harekete. -execdirBunun yerine kullanırsanız -exec, belirtilen komut eşleşen dosyayı içeren alt dizinden çalıştırılır. Böylece, tüm yolu geçmek yerine, renamesadece geçer ./filename. Bu regex yazmak için çok daha kolay hale getirir.
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
Detayda:
-type f dizinleri değil yalnızca dosyaları aramak anlamına gelir-name '*.abc' sadece .abc ile biten dosya isimleri ile eşleşir'{}'-execdirbulunan yolu ekleyeceği yeri işaretleyen yer tutucudur . Tek tırnak, dosya adlarını boşluk ve kabuk karakterleriyle işlemesini sağlamak için gereklidir.-typeve -nameBash satır devam karakteri. Bu örneği daha okunaklı hale getirmek için onları kullanıyorum, ancak komutunuzu tek bir satıra yerleştirirseniz bunlara gerek kalmaz.-execdirhattın sonundaki ters eğik çizgi gerekir. Tarafından çalıştırılan komutu sonlandıran noktalı virgülden kaçmak için var -execdir. Eğlence!Regex'in açıklaması:
s/ regex'in başlangıcı\.\/öncü ile eşleşir. / that -execdir içeri girer. ve / meta karakterleri (not: bu bölüm sürümünüze bağlı olarak değişir find. user @ apollo adlı kullanıcının yorumuna bakın)(.+)dosya adıyla eşleş. Parantezler daha sonra kullanmak üzere eşleşmeyi yakalar\.abc noktadan kaçmak, abc eşleştirmek$ dizenin sonunda eşleşmeyi tuttur
/ regex'in "eşleşme" bölümünün sonunu ve "değiştirme" bölümünün başlangıcını işaretler
version1_ bu dosyayı her dosya adına ekle
$1varolan dosya adına atıfta bulunur, çünkü parantez içinde yakaladık. "Eşleşme" bölümünde birden fazla parantez seti kullanıyorsanız, buraya $ 2, $ 3 vs. kullanarak başvurabilirsiniz..abcyeni dosya adı .abc ile bitecektir. Burada "değiştir" bölümünde nokta meta karakterinden kaçmaya gerek yok/ regex'in sonuÖnce
tree --charset=ascii
|-- a_file.abc
|-- Another.abc
|-- Not_this.def
`-- dir1
`-- nested_file.abc
Sonra
tree --charset=ascii
|-- version1_a_file.abc
|-- version1_Another.abc
|-- Not_this.def
`-- dir1
`-- version1_nested_file.abc
İpucu: rename's -n seçeneği kullanışlıdır. Kuru bir işlem yapar ve hangi isimlerin değişeceğini gösterir, ancak herhangi bir değişiklik yapmaz.
--execdirgeçemedi . Mayıs, OSX’te değilim çünkü ubuntu değil./\.\/
Başka bir taşınabilir yol:
find /the/path -depth -type f -name "*.abc" -exec sh -c 'mv -- "$1" "$(dirname "$1")/$(basename "$1" .abc).edefg"' _ '{}' \;
# Rename all *.txt to *.text
for f in *.txt; do
mv -- "$f" "${f%.txt}.text"
done
Ayrıca neden ayrıştırmamanız gerektiği konusuna bakın ls.
Düzenleme: Eğer bazename kullanmak zorundaysanız, sözdiziminiz:
for f in *.txt; do
mv -- "$f" "$(basename "$f" .txt).text"
done
https://unix.stackexchange.com/questions/19654/changing-extension-to-multiple-files
Ben de aynen istediğim gibi yaptım ve çalıştım. mvKomutu kullandım . Birden fazla .3gpdosyam vardı ve hepsini yeniden adlandırmak istedim..mp4
İşte bunun için kısa bir oneliner:
for i in *.3gp; do mv -- "$i" "ren-$i.mp4"; done
Basitçe geçerli dizini tarar, tüm .3gp dosyalarını alır, sonra (mv kullanarak) yeniden adlandırır ren-name_of_file.mp4
file.3gpiçin file.3gp.mp4çoğu insan ne istediğini olmayabilir, hangi.
.3gpVeya .mp4burada örnek amacıyla sadece idi.
basename "$i" .mp4"ren- $ i.mp4" yerine önceki uzantıyı kaldırmak için kullanırdım.
Bana kalırsa doğru mmv komutunu gelen aynı adlı pakette :
mmv ';*.abc' '#1#2.edefg'
;Maçları sıfır veya daha fazla */ve karşılık gelen #1replasmanı. Karşılık *gelir #2. Özyinelemeli olmayan sürüm
mmv '*.abc' '#1.edefg'
Dosya ve klasörleri yeniden adlandır find -execdir | rename
Hem dosyaları hem de dizinleri sadece bir sonek ile değil, yeniden adlandıracaksanız, bu iyi bir kalıptır:
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find . -depth -execdir rename 's/findme/replaceme/' '{}' \;
Awesome -execdirseçeneği cd, renamekomutu çalıştırmadan önce dizine a yapar -exec.
-depth eksik ebeveyn dizinleri ile ilgili olası sorunları önlemek için yeniden adlandırma işleminin önce çocuklar üzerinde, sonra ebeveynler üzerinde yapıldığından emin olun.
-execdir Yeniden adlandırma, taban adı olmayan girdi yollarıyla iyi çalışmadığı için gereklidir, örneğin aşağıdakiler başarısız olur:
rename 's/findme/replaceme/g' acc/acc
Bilgisayar PATHkorsanlığı gereklidir, çünkü -execdirçok can sıkıcı bir dezavantajı vardır: findson derece tartışılır ve ortam değişkeninizde -execdirgöreceli yollarınız varsa PATH, örneğin ./node_modules/.bin:
find: './node_modules/.bin' göreceli yolu, find -execdir eylemiyle birlikte güvensiz olan PATH ortam değişkenine dahil edilir. Lütfen bu girişi $ PATH içinden kaldırın
Ayrıca bakınız: Neden '-execdir' eylemini kullanmak PATH'taki dizin için güvensiz?
-execdirPOSIX için bir GNU bulma uzantısıdır . renamePerl tabanlı ve renamepaketten geliyor . Ubuntu 18.10'da test edilmiştir.
Lookahead geçici çözümünü yeniden adlandır
Girdi yollarınız gelmiyorsa findveya göreceli yol sıkıntısından yeterince kurtulduysanız, dizinleri aşağıdaki gibi güvenli bir şekilde yeniden adlandırmak için bazı Perl görünümlerini kullanabiliriz:
git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'
Ben için uygun bir analog bulamadık -execdirile xargs: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686
sort -rUzun yollar aynı öneki ile kısa olanlar peşine beri dosyaları kendi dizinleri sonra gelmek sağlamak için gereklidir.