ディレクトリを平面化しますが、新しいファイル名にディレクトリ名を保持します。

ディレクトリを平面化しますが、新しいファイル名にディレクトリ名を保持します。

ディレクトリを次の形式にどのようにフラット化できますか?

今後:./aaa/bbb/ccc.png

後ろに:./aaa-bbb-ccc.png

答え1

これにはすでに良い答えがありますが、次はより直感的だと思いますbash

find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \;

aaa既存のディレクトリはどこにありますか?ここに含まれるファイルは現在のディレクトリに移動されます(aaaには空のディレクトリのみが残ります)。これら2つの呼び出しはtrディレクトリとスペースを処理します(スラッシュをエスケープする論理なし - 読者のための練習)。

私はこれがより直感的で比較的調整しやすいと思います。findつまり、.pngファイルのみを見つけるためにパラメータを変更できます。tr通話を変更するか、必要に応じて追加できます。正しく機能しているかどうかを視覚的に確認するには、echoまず追加し、追加の手順なしに問題が正しく表示される場合にのみ繰り返します。mvecho

find aaa -name \*.png -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); echo mv "{}" "$new"' \;

また、...または...の代わりにfind aaa...を使用したことに注意してください。後者の2つは最終ファイル名に興味深い痕跡を残すからです。find .find aaa/

答え2

警告:ほとんどのコマンドをブラウザに直接入力しました。講師に警告してください。

zshを使ってズマブ:

zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'

説明:このパターンは、**/*現在のディレクトリのサブディレクトリにあるすべてのファイルを繰り返し一致します(現在のディレクトリのファイルと一致しませんが、これらのファイルの名前を変更する必要はありません)。角かっこの最初の2つのペアは、代替テキストで合計として参照できる$1グループです。$2最後の角かっこペアを追加します。D グローバル予選これにより、ファイルが欠落しません。既存のファイルを上書きするかどうかを尋ねるメッセージを表示するために-o -iこの-iオプションを渡すことを意味します。mv


POSIXツールのみを使用してください。

find . -depth -exec sh -c '
    for source; do
      case $source in ./*/*)
        target="$(printf %sz "${source#./}" | tr / -)";
        mv -i -- "$source" "${target%z}";;
      esac
    done
' _ {} +

説明: このcaseステートメントは、現行ディレクトリーと現行ディレクトリーの最上位サブディレクトリーを省略します。先行が削除され、すべてのスラッシュがダッシュで置き換えられたtargetソースファイル名()が含まれます。最後は、ファイル名が改行で終わるのを防ぐことです。それ以外の場合、コマンド置換はそれを削除します。$0./zz

findあなたがそれをサポートしていない場合-exec … +(OpenBSD、私はあなたを探しています):

find . -depth -exec sh -c '
    case $0 in ./*/*)
      target="$(printf %sz "${0#./}" | tr / -)";
      mv -i -- "$0" "${target%z}";;
    esac
' {} \;

bash(またはksh93)を使用すると、スラッシュをダッシュ​​に置き換えるために外部コマンドを呼び出す必要はありません。文字列置換設定でksh93パラメータ拡張を使用できます${VAR//STRING/REPLACEMENT}

find . -depth -exec bash -c '
    for source; do
      case $source in ./*/*)
        source=${source#./}
        target="${source//\//-}";
        mv -i -- "$source" "$target";;
      esac
    done
' _ {} +

答え3

find . -mindepth 2 -type f -name '*' |
  perl -l000ne 'print $_;  s/\//-/g; s/^\.-/.\// and print' |
    xargs -0n2 mv 

注:これはインクルードでは機能しません\n
もちろん、これはタイプfファイルだけを移動します。
唯一の名前の競合は、従来から発生します。パスワード

テストにはこのデフォルトのサブセットを使用してください。

rm -fr junk
rm -f  junk*hello*

mkdir -p  junk/junkier/junkiest
touch    'hello    hello'
touch    'junk/hello    hello'
touch    'junk/junkier/hello    hello'
touch    'junk/junkier/junkiest/hello    hello'

~につながる

./hello    hello
./junk-hello    hello
./junk-junkier-hello    hello
./junk-junkier-junkiest-hello    hello

答え4

ファイル名+パスをtrコマンドにパイプするだけです。tr <replace> <with>

for FILE in `find aaa -name "*.png"`
do
  NEWFILE=`echo $FILE | tr '/' '-'`
  cp -v $FILE $NEWFILE
done

関連情報