シェルスクリプトのすべてのサブディレクトリからスペースを削除する方法は?

シェルスクリプトのすべてのサブディレクトリからスペースを削除する方法は?

下線付きの空白をすべて削除するには、次のシェルスクリプトを試しました。

find $1 -depth -name "* *" -print0 | \
while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done

ディレクトリが存在すると、ディレクトリが/home/user/g h/y h/u j/修正され、エラーが発生します。y hy_h/home/user/g h/y h/u j

No such file or directory

答え1

これを使用してください:

find -name "* *" -print0 | sort -rz | \
  while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done

find名前にスペースを含むファイルとフォルダが検索されます。-print0特殊ファイル名を処理するには、ヌルバイトを区切り文字として使用してprint()します。

sort -rzフォルダの最も深いファイルが最初に移動され、フォルダ自体が最後に移動されるようにファイルの順序を逆にします。したがって、フォルダ内のすべてのファイルとフォルダ名が変更されるまで、フォルダ名は変更されません。

最後に、このmvコマンドはファイル/フォルダの名前を変更します。ターゲット名では、ファイルのデフォルト名からスペースのみを削除します。そうしないと、アクセスできなくなります。

答え2

find $1 -depth -name "* *" -type d -execdir rename 's/ /_/g' "{}" \;

答え3

basenameファイル名(パスの姓など)と次に区別されますdirname

find $1 -depth -name "* *" -print0 | \
while read -d $'\0' f ; do
    a="$(dirname "$f")"
    b="$(basename "$f")"
    #optional check if the basename changes -> reduces errors in mv command
    #only needed when using -wholename instead of -name in find, so skippable
    if [ "${b// /_}" != "$b" ] ; then
      mv -v "$a"/"$b"  "$a"/"${b// /_}"
    fi
done

-depth親ディレクトリを変更する前に、まずサブディレクトリを変更する問題が仕様で解決されましたfind

関連情報