Yanıtlar:
Tüm dizinler tek bir seviyede mi, özyinelemeli mi?
Bir seviyede:
autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'
Tekrarlı:
zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'
Açıklamalar: zmv
bir kalıpla eşleşen dosyaları verilen değiştirme metnine göre yeniden adlandırır. seçeneği başlık altındaki her komuta -o-i
geçirir (aşağıya bakın). Yedek Metinde, , , vb desende ardışık parantez gruplardır. tüm (alt) * dizinleri yinelemeli olarak ifade eder. Final , parantez içine alınmış bir grup değil, yalnızca dizinlerle eşleşmesi anlamına gelen bir glob niteleyicisi. küçük harfe dönüştürür .-i
mv
$1
$2
**
(/)
${2:l}
$2
Bir seviyede:
for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done
Final /
, dizinlerle eşleşmeyi kısıtlar ve mv -i
bir çarpışma durumunda onay ister. Kaldır -i
bir çarpışma ve kullanım durumunda üzerine yazmak yes n | for …
. istenmez ve çarpışacak yeniden adlandırma işlemi gerçekleştirilmez.
Tekrarlı:
find root/* -depth -type d -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;
Kullanımı -depth
derinden iç içe dizinleri atalarının önce işlenir sağlar. Ad işleme, orada bir /
; geçerli dizinde ./*
opera çağırmak istiyorsanız, (kabuk betiğini başa çıkmak için uyarlamak .
veya *
okuyucu için bir egzersiz olarak bırakmak ).
Burada Debian ve Ubuntu'nun gönderdiği Perl yeniden adlandırma komut dosyasını kullanıyorum /usr/bin/prename
(genellikle de mevcuttur rename
). Bir seviyede:
rename 's!/([^/]*/?)$!\L/$1!' root/*/
Yinelemeli, bash h4 veya zsh ile:
shopt -s globstar # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/
Özyinelemeli, taşınabilir:
find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
-execdir
hangi harika olduğunu buldum : unix.stackexchange.com/questions/5412/… Sonra biraz PATH
delilik olduğunu ve üzgün olduğunu buldum :-(
Bunu yapacak tek bir komut yoktur, ancak böyle bir şey yapabilirsiniz:
for fd in */; do
#get lower case version
fd_lower=$(printf %s "$fd" | tr A-Z a-z)
#if it wasn't already lowercase, move it.
[ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"
done
Sağlam olması gerekiyorsa, yalnızca iki durumda farklı olan iki dizin bulunduğunu dikkate almalısınız.
Tek astar olarak:
for fd in */; do fd_lower=$(printf %s "$fd" | tr A-Z a-z) && [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"; done
for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
find -type d
, ama tam olarak alamadım
for fd in */;
, bu yüzden bir dizin olup olmadığını kontrol ihtiyacını kaçınmak olurdu, ama bu içgüdünün iyi bir olup olmadığını bilmiyorum.
tr
Zaten bir dizi beklediğini yüzden tr '[A-Z]' '[a-z]'
çevirir [
etmek [
ve ]
karşı ]
geçerken. Bu işe yaramaz ama zararsızdır; ancak geçerli dizinde tek büyük harfli bir dosya varsa, tırnak işaretleri olmadan kabuk parantezleri genişletir.
Bunu tek satırlık bir meydan okuma olarak aldım :) İlk olarak, bir test örneği oluşturun:
$ for d in foo Bar eVe; do mkdir -p dcthis/$d; touch dcthis/a${d}.txt; done
$ ls dcthis/
Bar aBar.txt aeVe.txt afoo.txt eVe foo
Kullandığım find
büyük harf olan dizinleri nokta ve ardından yoluyla bunları downcase için . Sanırım kullanmak biraz hack-ish, ama doğrudan şeylerden kaçmayı denediğimde kafam her zaman patlar .sh -c 'mv {}
echo {} | tr [:upper:] [:lower:]
'sh -c
find
$ (cd dcthis && find . -maxdepth 1 -type d -path '*[A-Z]*' -exec sh -c 'mv {} `echo {} | tr [:upper:] [:lower:]`' \;)
$ ls dcthis/
aBar.txt aeVe.txt afoo.txt bar eve foo
Dikkat edin: Bu çözüm, downcasing'in çarpışmalara yol açıp açmadığını kontrol etmez!
mv -i
. Daha büyük bir sorun, doğru alıntı kullanmamanızdır, bu nedenle \[*?
adın herhangi bir yerinde özel karakterler (boşluk veya ) varsa komutunuz başarısız olur . find
Tekrar etmedikçe kullanmanın bir anlamı yok, sonra ihtiyacınız var find -depth
ve -path
olmalı -name
. Çalışma örnekleri için cevabıma bakın.
mv -i
yazdıktan sonra gördüm . Alıntı ile iyi bir nokta ...
find -execdir
| Adını değiştirmek
Göreceli yol deliliği için olmasaydı bunu yapmanın en iyi yolu olurdu, çünkü Perl regex fu'nun sadece taban adına etki etmesini önler:
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find a -depth -execdir rename 's/(.*)/\L$1/' '{}' \;
-execdir
İlk cd
yalnızca basename üzerinde çalıştırmadan önce dizine s.
Ne yazık ki, o PATH
hack bölümünden kurtulamıyorum, find -execdir
göreceli bir yolunuz varsa hiçbir şey yapmayı reddediyorum PATH
...: /ubuntu/621132/why-using-the-execdir-action- is-güvensiz-için-dizinine-olan-in-the-yolu / 1109378 # 1109378
mv -i a a
"mv: a / a: geçersiz argüman" a yeniden adlandır.