ファイル名とディレクトリ名にドットを含むサブディレクトリを含むディレクトリがあります。
$ ls -R
.:
dir file.with.dots
./dir:
subdir.with.dots
./dir/subdir.with.dots:
other.file
現在、フォルダとフォルダ自体find
の名前を変更したくないので、これらすべてのファイルをキャプチャするのは本当に難しいです。.
..
私も方法を読んだ。拡張子を変更せずにファイル名の点を下線に変更します。しかし、主な問題はファイルを再帰的に選択することであるため、これには適していません。
find
点をとに変更しようとしましたtr
。
find $(pwd) -depth -name '*.*'|while read f; do mv -iv "$f" '"'$(echo $f|tr '.' '_')'"' ; done
ただし、ファイルパスとファイル自体にドットの両方が含まれているとエラーが発生します。
すべての点の名前を変更して下線に変更するにはどうすればよいですか?
答え1
そしてzsh
:
autoload zmv
zmv '(**/)(*.*)' '$1${2//./_}'
それ以外の場合は、アクセス権がある場合bash
(アクセスする予定ksh93
)、いつでも次のことができます。zsh
find . -depth ! -name '.*' -name '*.*' -exec bash -c '
for file do
dir=${file%/*}
base=${file##*/}
mv -i -- "$file" "$dir/${base//./_}"
done' sh {} +
(たとえあなたが行った完全性チェックを見逃すでしょうzmv
)。
これは(意図的に)隠されたファイルの名前を変更しません。
要点は、リストを深く優先して処理し(デフォルトzmv
で実行され、で-depth
使用されるfind
)、ファイルのデフォルト名のみを変更することです。
これにより、次のことができます。
mv -- a.b/c.d a.b/c_d
そしてそれから:
mv -- a.b a_b
また、zmv以外のソリューションの場合は、同じディレクトリにファイルとディレクトリがある場合はa.b
幸せになります。a_b
mv -- a.b a_b
a.b
入力する a_b/
。これを防ぐには、GNUシステムの場合、-T
このオプションをmv
。
ご覧のとおり、ループwhile read
を使用するために回答を編集してみました。
while read
1行に1つのコマンドを実行する必要がある場合でも、通常ループは避けるべきです。 1つを使用したい場合は、正しく使用するのが難しく、ksh / bash / zshismsが必要です。
{
find . -depth ! -name '.*' -name '*.*' -exec printf '%s\0' {} + |
while IFS= read -rd '' file; do
dir=${file%/*}
base=${file##*/}
mv -i -- "$file" "$dir/${base//./_}"
done <&3 3<&-
} 3<&0
(あなたの発見がそれをサポートするならば、これを置き換えることができます-exec printf '%s\0' {} +
)。-print0
以下を行う必要があります。
-print0
/-exec printf '%s\0' {} +
改行はファイル名で有効な文字なので、改行を区切り文字として使用できないためです。- だからあなたは必要です
-d ''
(read
NLの代わりにNULまで読んでください) IFS=
IFS
(つまり、forからすべての空白文字を削除しread
、それ以外の場合は入力レコードの末尾から空白文字を削除します)。-r
それ以外の場合、read
バックスラッシュはエスケープ文字として扱われます(フィールドとレコードの区切り文字として使用されます)。- ファイル記述子と踊るその小さな男これは、標準入力がパイプではなく
mv
端末(-i
プロンプトへの応答用)になりたいからですfind
。