回答:
1つのレベルのすべてのディレクトリ、または再帰的に?
1つのレベルで:
autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'
再帰的に:
zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'
説明:zmv
指定された置換テキストに従って、パターンに一致するファイルの名前を変更します。-o-i
内部の-i
各mv
コマンドにオプションを渡します(以下を参照)。置換テキストでは、$1
、$2
、など、パターン中の連続括弧基です。**
すべての(サブ)*ディレクトリを再帰的に意味します。final (/)
は括弧で囲まれたグループではなく、ディレクトリのみに一致することを意味するglob修飾子です。小文字に${2:l}
変換$2
します。
1つのレベルで:
for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done
最終版で/
は、ディレクトリへの一致を制限しmv -i
、衝突が発生した場合に確認を求めます。-i
衝突の場合に上書きするを削除し、を使用しますyes n | for …
。プロンプトが表示されず、衝突する名前変更を実行しないようにします。
再帰的に:
find root/* -depth -type d -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;
を使用-depth
すると、深くネストされたディレクトリが祖先の前に処理されます。名前の処理は/
、現在のディレクトリで操作を呼び出したい場合は、./*
(シェルスクリプトを適応させる.
か*
、読者の演習として残しておきます)を使用します。
ここでは、DebianおよびUbuntuに同梱されているPerlの名前変更スクリプトを使用し/usr/bin/prename
ます(通常も利用可能ですrename
)。1つのレベルで:
rename 's!/([^/]*/?)$!\L/$1!' root/*/
再帰的に、bash≥4またはzshで:
shopt -s globstar # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/
再帰的に移植可能:
find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
-execdir
素晴らしいである:unix.stackexchange.com/questions/5412/...私は、それはいくつか持っていることがわかったPATH
狂気をして:-(悲しかった
それを行うコマンドは1つではありませんが、次のようなことができます。
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
堅牢にする必要がある場合は、大文字と小文字が異なるだけの2つのディレクトリが既に存在する場合を考慮する必要があります。
ワンライナーとして:
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
、それを得ることができませんでした
for fd in */;
そうすることでしたので、それがディレクトリであるかどうかのチェックの必要性を回避しますが、この本能が良いものであるかどうかはわかりません。
tr
すでに範囲を期待しているので、とにtr '[A-Z]' '[a-z]'
変換[
します。これは無意味ですが、無害です。ただし、引用符なしでは、現在のディレクトリに1文字の大文字の名前のファイルがある場合、シェルは括弧を展開します。[
]
]
私はこれをワンライナーの挑戦として受け止めました:)最初に、テストケースを確立します:
$ 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
私はfind
、大文字でディレクトリを見つけて、でそれらを小文字にするために使用します。使用するのはちょっとハックっぽいですが、直接逃げようとすると頭がいつも爆発します。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
警告:このソリューションでは、ダウンケーシングが衝突につながるかどうかはチェックしません!
mv -i
。より大きな問題は、適切な引用符を使用していないため\[*?
、名前のどこかに特殊文字(空白または)があるとコマンドが失敗することです。find
再帰しない限り、使用する意味はfind -depth
あり-path
ません-name
。そして、必要であり、そうでなければなりません。実例については私の答えをご覧ください。
mv -i
これを書いてからあなたを見ました。引用の良い点
find -execdir
| リネーム
これは、Perlの正規表現fuがベース名にのみ作用することを回避するため、相対パスの狂気のためでなければ、それを行うための最良の方法でしょう。
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find a -depth -execdir rename 's/(.*)/\L$1/' '{}' \;
-execdir
最初 cd
ベース名でのみ実行する前に、ディレクトリに移動します。
残念ながら、私はそれを取り除くことができないPATH
ハッキング一部、find -execdir
あなたが相対パスを持っている場合は何もすることを拒否PATH
...:/ubuntu/621132/why-using-the-execdir-action-パスに対して安全でないディレクトリに対して11/1197#1109378
mv -i a a
ます。「mv:名前をa / a:無効な引数」に指定します。