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
rename
Ubuntu'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/**/*.abc
Bash'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 -execdir
bu sorunu çözmek için harekete. -execdir
Bunun 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, rename
sadece 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'{}'
-execdir
bulunan 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.-type
ve -name
Bash 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.-execdir
hattı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
$1
varolan 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..abc
yeni 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.
--execdir
geç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. mv
Komutu kullandım . Birden fazla .3gp
dosyam 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.3gp
için file.3gp.mp4
çoğu insan ne istediğini olmayabilir, hangi.
.3gp
Veya .mp4
burada ö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 #1
replasmanı. 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 -execdir
seçeneği cd
, rename
komutu ç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 PATH
korsanlığı gereklidir, çünkü -execdir
çok can sıkıcı bir dezavantajı vardır: find
son derece tartışılır ve ortam değişkeninizde -execdir
gö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?
-execdir
POSIX için bir GNU bulma uzantısıdır . rename
Perl tabanlı ve rename
paketten geliyor . Ubuntu 18.10'da test edilmiştir.
Lookahead geçici çözümünü yeniden adlandır
Girdi yollarınız gelmiyorsa find
veya 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 -execdir
ile xargs
: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686
sort -r
Uzun yollar aynı öneki ile kısa olanlar peşine beri dosyaları kendi dizinleri sonra gelmek sağlamak için gereklidir.