次の形式でディレクトリをフラット化するにはどうすればよいですか?
前: ./aaa/bbb/ccc.png
後: ./aaa-bbb-ccc.png
./foo/bar/baz.png、./foo-bar-baz.png両方が存在する可能性のあるケースをどのように処理するかを指定する必要もあります。後者を前者に置き換えたくないと思いますか?
                次の形式でディレクトリをフラット化するにはどうすればよいですか?
前: ./aaa/bbb/ccc.png
後: ./aaa-bbb-ccc.png
./foo/bar/baz.png、./foo-bar-baz.png両方が存在する可能性のあるケースをどのように処理するかを指定する必要もあります。後者を前者に置き換えたくないと思いますか?
                回答:
警告:これらのコマンドのほとんどをブラウザに直接入力しました。警告講師。
zshおよびzmvの場合:
zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'
説明:パターン**/*は、現在のディレクトリのサブディレクトリにあるすべてのファイルに再帰的に一致します(現在のディレクトリにあるファイルには一致しませんが、これらの名前を変更する必要はありません)。括弧の最初の二対として参照されることができる基であり、$1そして$2置換テキストに。括弧の最後のペアはD glob修飾子を追加して、ドットファイルが省略されないようにします。既存のファイルが上書きされるかどうかを尋ねるようにオプション-o -iを渡すことを意味します。-imv
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)が含まれ、先頭の./文字が取り除かれ、すべてのスラッシュがダッシュに置き換えられ、最後にが含まれzます。最後zは、ファイル名が改行で終わっている場合に存在します。それ以外の場合、コマンド置換はそれを取り除きます。
あなた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
' _ {} +
for sourceあなたは(通常は)使用している理由としては、最初に提示したファイル/ディレクトリを欠場...私は最終的に出て発見した_として$0:) ...と偉大な答えてくれてありがとう。私は彼らから多くを学びます。
                    ここには良い答えがありますが、これはより直感的ですbash:
find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \;
aaa既存のディレクトリはどこですか。そこに含まれるファイルは現在のディレクトリに移動されます(aaaには空のディレクトリのみが残ります)。trディレクトリとスペースの両方を処理するための2つの呼び出し(エスケープされたスラッシュのロジックなし-読者のための練習)。
これはより直感的で、調整が比較的簡単だと思います。findつまり、.pngファイルのみを検索する場合は、パラメータを変更できます。tr通話を変更したり、必要に応じて追加したりできます。そして、それが正しいことを視覚的に確認したい場合は、echo前に追加できますmv(次にecho、物事が正しく見える場合にのみ、追加なしで繰り返します:
find aaa -name \*.png -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); echo mv "{}" "$new"' \;
また、find aaa...と...ではなくfind .... を使用していることに注意してくださいfind aaa/。後者の2つは、最終的なファイル名に面白いアーティファクトを残すためです。
find . -mindepth 2 -type f -name '*' |
  perl -l000ne 'print $_;  s/\//-/g; s/^\.-/.\// and print' |
    xargs -0n2 mv 
注:これは、を含むファイル名では機能しません\n。
もちろん、これはタイプfファイルのみを移動します... 
名前の衝突は、pwdに既存のファイルからのみです。  
この基本的なサブセットでテスト済み
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
これはlsバージョンです。コメントは歓迎します。このような奇抜なファイル名でも機能します 
 "j1ळ\n\001\n/j2/j3/j4/\nh  h\n"が、落とし穴を知りたいと思っています。それは「悪意のある人がls実際に(頑強に)できるか」の練習問題です。  
ls -AbQR1p * |                        # paths in "quoted" \escaped format
    sed -n '/":$/,${/.[^/]$/p}' |     # skip files in pwd, blank and dir/ lines
    { bwd="$PWD"; while read -n1;     # save base dir strip leading "quote
                        read -r p; do # read path
        printf -vs "${p%\"*}"         # strip trailing quote"(:)
        [[ $p == *: ]] && {           # this is a directory
            cd   "$bwd/$s"            # change into new directory
            rnp="${s//\//-}"-         # relative name prefix
        } || mv "$s" "$bwd/$rnp$s"
      done; }
ファイル名+パスをtrコマンドにパイプするだけです。tr <replace> <with>
for FILE in `find aaa -name "*.png"`
do
  NEWFILE=`echo $FILE | tr '/' '-'`
  cp -v $FILE $NEWFILE
donecp行を変更しcp -v "$FILE" "$NEWFILE"ますか?(また、pngファイルのみを想定するべきではありません。)
                    cp行に引用符を追加するだけでは不十分です。ループを使用してfind出力を解析するアプローチ全体にfor欠陥があります。使用する唯一の安全な方法がfindである-exec、または-print0(より少ないポータブル可能な場合-exec)。より堅牢な代替案をお勧めしますが、あなたの質問は現時点では不十分です。
                    ファイル名のスペースに安全:
#!/bin/bash
/bin/find $PWD -type f | while read FILE
do
    _new="${FILE//\//-}"
    _new="${_new:1}"
    #echo $FILE
    #echo $_new
    /bin/mv "$FILE" "$_new"
done
明らかな理由でではcpなくを使って鉱山を走らmvせましたが、同じものを生産するはずです。
type find-> find is /usr/bin/find私のマシンで。PATHスクリプトで変数名として使用するのはひどい考えです。また、readコマンドを誤用しているため、スクリプトはファイル名をスペースまたはバックスラッシュでマングルします(このサイトでを検索してくださいIFS read -r)。
                    find is hashed (/bin/find)、関連する方法?異なるディストリビューションは異なりますか?
                    PATH環境変数のポイントが不足していることを示唆しているようです。これは、すべての Unixシステムが使用しているものです。あなたが書いた/bin/find場合、スクリプトは実際にはないすべてのシステム(Gilles、mine、おそらくOP)で壊れています/bin/find(たとえば、b / cはにあります/usr/bin/find)。PATH環境変数の要点は、これを問題にしないことです。
                    $(pwd)は変数で既に使用可能です:$PWD。ただし、ここでは絶対パスを使用しないでください。たとえば、スクリプトがから呼び出された場合、スクリプトは/home/timに名前/home/tim/some/pathを変更しようとし/home-tim-some-pathます。