私はMacを使用しているので、mvは少し異なり、その--backup
プロパティをサポートしていません。私が思いつく最善の方法は次のとおりです。
find . -mindepth 2 -type f -print -exec mv {} . \;
答え1
いくつかのスクリプトを書く必要があります。それは次のとおりです。
find . -mindepth 2 -type f -print | while read x; do
y=$(basename "$x")
if [ -f "$y" ]; then
mv "$y" "$y".backup
fi
mv "$x" "$y"
done
答え2
mv
ディレクトリーでない場合に target コマンドの単純バックアップを作成するには、次のようにします。
if [ -e "$target" ] && [ ! -d "$target" ]; then
mv "$target" "$target.backup"
fi
$target.backup
既存のディレクトリであれば、明らかに望ましくない結果につながります。また、既存の項目が$target.backup
ある場合は上書きされます。
列挙バックアップ方式を使用する方が安全です。
mv
ディレクトリーでない場合に target コマンドの列挙バックアップを作成するには、次のようにします。
suffix=1
if [ -e "$target" ] && [ ! -d "$target" ]; then
while [ -e "$target.$suffix" ]; do
suffix=$(( suffix + 1 ))
done
mv "$target" "$target.$suffix"
fi
これにより、$target
ファイル名を無効にする$target.N
最初の正の整数名が変更されます。N
$target.N
しかし、ここには競争条件があることに注意してください。その他このコードのインスタンス(または完全に関連していないプロセス)は、名前が$target.$suffix
使用されていないことを検出して$target
その名前に移動する間に生成できます。
これを防ぐには:
suffix=1
if [ -e "$target" ] && [ ! -d "$target" ]; then
while [ -d "$target.$suffix" ] ||
! ln "$target" "$target.$suffix" 2>/dev/null; do
suffix=$(( suffix + 1 ))
done
fi
ln
今私たちは新しい名前(ハードリンク)$target
.の場合、既存のディレクトリの名前を生成する整数もスキップされます。無料の新しい名前が見つかるまで、この操作は失敗します。
それからあなたはできます
mv "$source" "$target"
find
以前と同様に、すべての一般ファイルを移動するには、次のコマンドを適用します。
find . -mindepth 2 -type f -print -exec sh -c '
for source do
target=${source##*/}
suffix=1
if [ -e "$target" ] && [ ! -d "$target" ]; then
while [ -d "$target.$suffix" ] ||
! ln "$target" "$target.$suffix" 2>/dev/null; do
suffix=$(( suffix + 1 ))
done
fi
mv "$source" "$target"
done' sh {} +
テスト:
$ tree
.
|-- dir1
| `-- file
|-- dir2
| `-- file
`-- dir3
`-- file
3 directories, 3 files
$ # the find command goes here
./dir1/file
./dir2/file
./dir3/file
$ tree
.
|-- dir1
|-- dir2
|-- dir3
|-- file
|-- file.1
`-- file.2
3 directories, 3 files
この例では、最後に見つかったファイル、以前に見つけたファイル、最初に見つかったファイルにfile
なります。file
file.2
file.1
find
残念ながら、macOSでの実装はmv -n
利用可能な終了ステータスを返しません。実行が失敗したときにゼロ以外の値が返された場合は、よりmv
少ない競合状態を使用してより簡単な方法で問題を解決できます。
答え3
これが私の最終結果です。
num=1
find . -mindepth 2 -type f -print | while read x; do
y=$(basename "$x")
if [ -f "$y" ]; then
mv "$y" "$y"."$num"
num=$(( $num + 1 ))
fi
mv "$x" "$y"
done
したがって、.backupを使用しないでください。同じ名前の別のバックアップがある場合は、まだ発生する可能性があります。インスピレーションありがとうございます!