Bir dizin altındaki tüm dizinleri küçültme


Yanıtlar:


10

Tüm dizinler tek bir seviyede mi, özyinelemeli mi?

zsh

Bir seviyede:

autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'

Tekrarlı:

zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'

Açıklamalar: zmvbir 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-igeç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 .-imv$1$2**(/)${2:l}$2

Taşınabilir

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 -ibir çarpışma durumunda onay ister. Kaldır -ibir ç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ı -depthderinden 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 ).

Perl adını değiştir

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!' {} +

En azından OS X'te, herhangi bir dizin zaten küçük harf durumunda başarısız olur: mv -i a a"mv: a / a: geçersiz argüman" a yeniden adlandır.
Janus

@Janus: Doğru, çirkin bir hata mesajı alıyorsunuz (komut satırında zararsız olsa da). Ama yine de bu davaya bakan zmv kullanmalıydım.
Gilles 'SO- şeytan olmayı bırak'

Sonra -execdirhangi harika olduğunu buldum : unix.stackexchange.com/questions/5412/… Sonra biraz PATHdelilik olduğunu ve üzgün olduğunu buldum :-(
Ciro Santilli at 病毒 审查 六四 事件 法轮功

4

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

Bu benim (temelde aynı) öneri yazarak ortasında ortaya çıktı:for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
frabjous

Çalışmaya çalışıyordum find -type d, ama tam olarak alamadım
Michael Mrozek

1
Benim içgüdüm yapmak olurdu 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.
Steven D

Evet, çünkü ... * / daha iyi olurdu.
Shawn J. Goff

1
@Shawn: trZaten 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.
Gilles 'SO- kötü olmayı bırak'

0

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 findbü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 -cfind

$ (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!


çarpışmaları kontrol etmek kolaydır 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 . findTekrar etmedikçe kullanmanın bir anlamı yok, sonra ihtiyacınız var find -depthve -patholmalı -name. Çalışma örnekleri için cevabıma bakın.
Gilles 'SO- şeytan olmayı bırak'

@Giles. Teşekkürler! Bunu mv -iyazdıktan sonra gördüm . Alıntı ile iyi bir nokta ...
Janus

0

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 cdyalnızca basename üzerinde çalıştırmadan önce dizine s.

Ne yazık ki, o PATHhack bölümünden kurtulamıyorum, find -execdirgö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

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.