ディレクトリ構造を平坦化するには、次のようにします。
find . -type f -exec sh -c 'mv "{}" "./`basename "{}"`"' \;
私のプロフィールに以下を保存したいと思います:$ FLATTEN
-exec sh -c 'mv "{}" "./`basename "{}"`"' \;
これにより、後で実行できます。find . $FLATTEN
早すぎると解釈され、変数を保存するのに問題があります。文字列リテラルとして保存してインポートするのではなく、シェルで使用した場合にのみ解釈したいと思います。
答え1
GNUを使用する場合は、mv
次のようにする必要があります。
find . -type f -exec mv -t . {} +
他の人mv
:
find . -type f -exec sh -c 'exec mv "$@" .' sh {} +
{}
コードを挿入しないでくださいsh
。これは、ファイル名がシェルコード(`reboot`
名前付きファイルを使用しようとするなど)として解釈されるため、コマンドインジェクションの脆弱性です。
quote コマンドの置換は良い点ですが、古代形式(`...`
代わりに$(...)
)を使用しているので、内部二重引用符またはsh
Bourne ShellまたはAT&T kshベースの実装では機能しません。(実際には矛盾"`basename "foo bar"`"
(このシェルでは許可されている)と見なされ、接続されます)。"`basename "
`
foo
bar"`"
また、次のことを行うとき:
mv foo/bar bar
bar
存在し、ディレクトリであれば実際にはディレクトリです。mv foo/bar bar/bar
そうmv -t . foo/bar
でなければ、mv foo/bar .
そのような問題はありません。
これで、これらのパラメータ(、、、、、、、、)を変数に格納するには-exec
配列変数が必要です。配列をサポートするシェルには、、、、、、、、などがあります。sh
-c
exec mv "$@" .
sh
{}
+
(t)csh
ksh
bash
zsh
rc
es
yash
fish
ksh/bash/yashまたは以外の$FLATTEN
変数を直接使用できるようにするには、合理的な配列実装を備えたシェルが必要です。また、ここではこれらのパラメータの中に空白がありません。"${FLATTEN[@]}"
$FLATTEN:q
(t)csh
rc
es
fish
zsh
存在するrc
/ es
/ zsh
:
FLATTEN=(-exec sh -c 'exec mv "$@" .' sh '{}' +)
存在するfish
:
set FLATTEN -exec sh -c 'exec mv "$@" .' sh '{}' +
その後、次のものを使用できます。
find . -type f $FLATTEN
答え2
これを達成して正しい結果を得るには、シェル関数を使用することをお勧めします(サブシェル-exec
に入れないでください)。{}
flatten () {
( cd "${1:-.}" &&
find . -type f -exec sh -c 'for n; do test -e "${n##*/}" || mv "$n" "${n##*/}"; done' sh {} + )
}
また、外部ユーティリティを呼び出す必要はなく、basename
すでに存在するものを上書きしようとしません。
これを使用するために入力すると、flatten
現在のディレクトリで動作します。ディレクトリ名を指定すると、そのディレクトリが実行されます(そのディレクトリの下のすべてのファイルをそのディレクトリの一番上にコピーします)。
答え3
関数はおそらく最良の方法でしょう。それ以外の場合は配列が必要ですeval
。
find_array=(-exec sh -c 'mv "{}" "./`basename "{}"`"' \;)
find . "${find_array[@]}"
または
FLATTEN="-exec sh -c 'mv \"{}\" \"./`basename \"{}\"`\"' \;"
eval find . $FLATTEN
答え4
機能はどうですか?
flatten(){
find "$@" -type f -exec sh -c 'mv -- "$0" "${0##*/}"' {} \;
}
使用法:
> flatten .
使用すると選択zsh
できます。これにより、コマンド名だけでなく、グローバルに挿入されるエイリアスも定義できます。-g
alias