次のいずれかを検索するには:
Linuxで空白で始まるフォルダを見つけて、フォルダが文字または数字で始まるようにすべての開始スペースを削除しますか?
Linuxで空白で始まるファイルを見つけて、ファイルが文字または数字で始まるように、すべての先行スペースを削除しますか?
答え1
find . -depth -name ' *' -exec sh -c '
for pathname do
newname=${pathname##*/}
newname=${newname#"${newname%%[! ]*}"}
newpathname=${pathname%/*}/$newname
if [ -z "$newname" ] || [ -e "$newpathname" ]; then
continue
fi
mv -v "$pathname" "$newpathname"
done' sh {} +
上記のコードは、名前が1つ以上の空白文字で始まる現在のディレクトリ内または下のすべてのファイルまたはディレクトリを検索します。コンテンツがまだ処理されていないディレクトリの名前を変更するのを防ぐために、深さ優先順にこの操作を実行します。-depth
そうしないと、ディレクトリの名前を変更すると名前がfind
変更されたため、後で見つけることができなくなります。
スペースで始まる名前のバッチに対して短いインラインシェルスクリプトを呼び出します。このスクリプトは与えられたパス名を繰り返し、最初に現在のパス名の末尾にある実際の名前を変数として抽出しますnewname
。これは、標準パラメータ置換を使用して${pathname##*/}
、文字列の最後のすべてのエントリ(最も長い接頭辞の一致)を削除し、最終パス名コンポーネントを残すようにこれを行います。これは基本的にこの例と同じです。/
*/
"$(basename "$pathname")"
その後、文字列の先頭に存在することを保証するスペースを切り捨てる必要があります$newname
。これを行うには、最初にスペースを除くすべての${newname%%[! ]*}
エントリ(最も長いサフィックスマッチ、つまりスペースではなく最初の文字から始まる)を削除し、次に文字列の先頭[! ]*
から結果を削除します。$newname
${newname#"${newname%%[! ]*}"}
コマンドの宛先パスは、mv
スラッシュで接続されたディレクトリパスと新しい名前ieで構成されます。これはデフォルトではieと同じです。$pathname
${pathname%/*}/$newname
"$(dirname "$pathname")/$newname"
このコードは、名前の競合を検出し、潜在的に競合する可能性のある名前の処理を自動的にスキップします。また、空の文字列に縮小される名前もスキップされます。これがif
前の陳述mv
がすることです。ユーザーがこれらの名前を認識できるようにするには、以前に実行してくださいcontinue
。
テストは以下で実行されます。コピーバックアップデータ。
上記のコードをテストしてみてください。
$ tree -Q
"."
|-- " dir0"
| |-- " o dir1"
| | |-- " otherfile"
| | `-- "dir2"
| | |-- " dir3"
| | `-- " moar"
| `-- "file"
`-- "script"
4 directories, 4 files
$ sh script
./ dir0/ o dir1/dir2/ moar -> ./ dir0/ o dir1/dir2/moar
./ dir0/ o dir1/dir2/ dir3 -> ./ dir0/ o dir1/dir2/dir3
./ dir0/ o dir1/ otherfile -> ./ dir0/ o dir1/otherfile
./ dir0/ o dir1 -> ./ dir0/o dir1
./ dir0 -> ./dir0
ディレクトリ階層の一番下からどのように開始されるかを確認してください。最初に名前を変更しようとすると、dir0
後で別のディレクトリとファイルの名前を変更するために入力することはできません。
$ tree -Q
"."
|-- "dir0"
| |-- "file"
| `-- "o dir1"
| |-- "dir2"
| | |-- "dir3"
| | `-- "moar"
| `-- "otherfile"
`-- "script"
4 directories, 4 files
答え2
スクリプトは空白で始まるファイルを検索し、実行するコマンドを出力します。このスクリプトが正しく機能するには、実際のmvコマンドのコメントを外す必要があります。目的のディレクトリで実行する必要があります。現在のディレクトリ内のすべてのファイルとフォルダは変更されますが、現在のディレクトリ内のサブディレクトリは変更されません。 " 123
"と ""という2つのファイルがあり、123
ディレクティブはそのファイルの名前を同じ内容に変更します。
元に戻せません。 mvに-iを追加したがユーザーが指定しない限り、ファイルは上書きされません。このスクリプトを実行する前に、システムがクラッシュした場合に備えてバックアップすることを含め、慎重に注意してください。
#!/bin/bash
# tell read not to word split
IFS=
# find all files starting with space
find ./ -maxdepth 1 -name " *" -print0 | \
while read -d '' a
do
# new filename without leading spaces
nm=$( echo "$a" | sed 's/^.\/ */.\//')
# use -i to not overwrite files
echo mv -i \"$a\" \"$nm\"
# uncomment the next line to do the actual move
#mv -i "$a" "$nm"
done
答え3
そしてzsh
:
autoload -Uz zmv
zmv -n '(**/) ##(*)(#qD/)' '$1$2'
(-n
満足したらテスト実行から削除)