使っていますケース。
次のコマンドが有効です。
$ mv camelCase (ccase -t Kebab camelCase)
ここで、次を使用して複数のディレクトリの名前を変更しようとします。
$ find . -type d -execdir rename 's/(.*)/$(ccase -t Kebab $1)/' '{}' \+
動作しません。次のエラーメッセージが表示されます。
Can't rename ./camelCase3 1000 4 24 27 30 46 121 132 1000ccase -t Kebab ./camelCase3): No such file or directory
どうですか?
答え1
しなければならない:
find . -depth ! -name . -type d -execdir sh -c '
for dir do
dir=${dir#*/} # remove the ./ prefix that some find implementations add
new_dir=$(ccase -t Kebab -- "$dir") || continue
[ "$dir" = "$new_dir" ] ||
mv -i -- "$dir" "$new_dir"
done' sh {} +
いいえそれらを{}
に含めるパスワードsh
/または言語ソルバーの引数がbash
原因で、コマンドインジェクションの脆弱性が発生します。バラより「find -exec sh -c」を使っても安全ですか?
その他の注意事項:
- 変数データがで始まらないことを保証できない場合は、オプションの終わりを表示するために
-
使用します。サポートされているか--
どうかは不明です。そうでない場合は、管理者にバグとして報告できます。ccase
--
- ここでは必要ありません
bash
。システムでsh
十分です。 - bashと同様に、shでもパラメータ拡張とコマンド置換は少なくともリストコンテキストで引用されなければなりません。それ以外の場合は分割+globを経ます!たとえば、参照してください。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク
- 特に、呼び出しなどの潜在的に破壊的なタスクを実行する場合は、
mv
実行するすべてのコマンドが成功したことを確認することをお勧めします。ここでは、失敗したディレクトリの|| continue
スキップを使用します。ccase
+
可能であれば、;
複数のディレクトリを渡さないでください。sh
これにより、ファイルごとのシェルが呼び出されるのを防ぎます。ただし、find
非標準述語をサポートするすべての実装がそう-execdir
するわけではありません。一部のBSDまたは以前のバージョンのfind
GNUでは、+
同じことをした;
後にループすることが重複しています(ただし無害ですが)。- はすでに存在する
mv -- SomeDir some_dir
ものと同じです。some_dir
ディレクトリまたはディレクトリへのシンボリックリンクですmv -- SomeDir some_dir/SomeDir
。 GNU実装を使用すると、オプションを使用してこれを回避mv
できます(または以下の方法を使用して競合を検出できます)。-T
zmv
これを回避し-execdir
、できるだけ少ない数のシェルを実行するには使用できますが、-exec
デフォルト名と親ディレクトリを区別する必要があります。改善として失敗を記録して終了ステータスccase
にmv
反映することもできます。find
find . -depth ! -name . -type d -exec sh -c '
ret=0
for dir do
base=${base##*/}
parent=${dir%/*}
new_base=$(ccase -t Kebab -- "$base") && {
[ "$base" = "$new_base" ] ||
mv -i -- "$dir" "$parent/$new_base"
} || ret=$?
done
exit "$ret"' sh {} +
上記では、たとえば、2つのファイルが同じ新しい名前で終わる場合など、データの損失を防ぐためのオプションをユーザーに提供するオプションを追加し-i
ました。より良いアプローチは、すべてを事前に確認し、テスト実行モード()を提供するmv
zshを使用することです。zmv
-n
autoload -Uz zmv
zmv -n '(**/)(*)(#q/)' '$1$(ccase -t Kebab -- $2)'
また、デフォルトでは隠しファイルを無視します。基本的に奥行き優先巡回を行います。この場合の終了ステータス(#q/)
は-type d
無視ccase
されます。名前が変更されていない場合、名前の変更は試行されません。
名前にすでにハイフンが含まれているファイルを処理したくない場合は、置き換える(*)
ことができます。(^*-*)
zshからKebabケースに変換することもできます。
zmv -n '(**/)(*)(#q/)' \
'$1${${${2//[_[:space:]]##/-}//(#b)([^[:upper:].-])([[:upper:]])/$match[1]-$match[2]}:l}'
スペースまたはアンダースコアのすべてのシーケンスを単一文字に変換し、大文字以外の文字(および除く)と基本名の大文字の間にsを挿入し、結果全体を-
小文字に変換します。代わりにに名前を変更するには調整する必要があります。-
.
-
l
AFileInTheUK.txt
a-file-in-the-u-k.txt
afile-in-the-uk.txt
答え2
ディレクトリの名前を1つずつ変更し、最も深いディレクトリから始めます。例えば
#!/bin/ksh93
find . -type d -depth -print | while read DIR ; do
PREFIX=${DIR%/*}
SUFFIX=${ ccase -t Kebab "${.sh.match:1}"; }
print mv "${DIR}" "${PREFIX}/${SUFFIX}"
done
その単語を削除する印刷スクリプトが要件を満たしていることを確認したら、スクリプトを準備してください;-)。
答え3
ここにあります。私が探しているコマンドは次のとおりです。
find . -depth -type d -execdir bash -c 'mv {} $(ccase -t Kebab {})' \;