ファイルとディレクトリの名前を繰り返し変更します。

ファイルとディレクトリの名前を繰り返し変更します。

このコマンドを使用してファイルの名前を変更します。

for fname in *;
do
    mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ')
done

ただし、現在のディレクトリでのみ名前が変更されます。多くのディレクトリがあり、各ディレクトリには異なるディレクトリが含まれ、最後のディレクトリツリーにはファイルが含まれているとします。任意の文字で名前を変更したいです。

私はそれがうまくいくべきだfind . -type fと思って試してみましたが、それでも操作コマンドを取得できませんでした。

答え1

そして、次を見つけてください。

find . -type f -exec sh -c 'SHELL COMMAND' {} \;

これはSHELL COMMAND見つかった各ファイルを順番に呼び出します。"$0"したがって、ファイル名はです。

find . -type f -exec sh -c '
    mv "$0" "${0%/*}/$(printf "%s\n" "${0##*/}" | sha1sum | cut -d" " -f1)"
' {} \;

(ファイル名がある場合、または問題を引き起こす可能性がある他の状況がある場合は、printf代わりに使用してください。)echo-e-necho

シェルを一括で呼び出すと、作業を高速化できます。

find . -type f -exec sh -c 'for x; do
      mv "$x" "${x%/*}/$(printf "%s\n" "${x##*/}" | sha1sum | cut -d" " -f1)";
    done' _ {} +

zshには、現在のディレクトリとサブディレクトリのすべてのファイルを再帰的に一致させる簡単な方法があります。これ. グローバル予選通常のファイルに一致を制限し、Dドットファイルを含めます。

for x in **/*(.D); do mv …; done

Bash ≥ 4では、再帰的に実行し、shopt -s globstar現在**/*のディレクトリとサブディレクトリのすべてのファイルを一致させるために使用できます。ループ内で通常のファイルをフィルタリングする必要があります。

shopt -s globstar; GLOBIGNORE=".:.."
for x in **/*; do if [[ -f $x ]]; then mv …; done

答え2

ヘルパースクリプト/tmp/tmp.shを作成します。

#!/bin/bash
mv "$1" $(echo "$1" | sha1sum | cut -f1 -d' ')

実行可能にしてから呼び出します。

find . -type f -execdir /tmp/tmp.sh {} ";"

答え3

Bash 4+を使用している場合は、次のことができます。

#!/bin/bash
shopt -s globstar
for fname in **/*; do 
  if [ -f "$fname" ]; then
    mv ...
  fi
done

Bash Hacker Wikiから:

新しいシェルオプションglobstarがあります。有効にすると、Bashは**で再帰的なワイルドカードを実行します。つまり、現在のレベルだけでなく、ファイルシステムの現在の場所にあるすべてのディレクトリとファイルと一致します。

http://wiki.bash-hackers.org/bash4

答え4

これはすべてのスペースを処理します...

set -f; IFS= 
while read -r -d $'\0' fname ;do
    mv ...
done < <(find . -type f -name '*' -print0)
set +f; IFS=$' \t\n' # you don't have to reset unless it effects subsequent code

関連情報