名前の競合が発生した場合にファイルとサブディレクトリを「サブディレクトリ」に移動する便利な方法は何ですか?

名前の競合が発生した場合にファイルとサブディレクトリを「サブディレクトリ」に移動する便利な方法は何ですか?

私のディレクトリにはいくつかのファイルとディレクトリがあります/var/foo/bar/baz。今私はそれらをすべてに移して/var/foo/barbazを削除したいと思います。簡単ですか?

cd /var/foo/bar
mv baz/* .
rmdir baz

(議論のために.で始まるファイルは無視されます。)

しかし!baz/名前にディレクトリ以外のファイルを含めるとどうなりますかbaz?別の場所に移動することも、一時ファイル名を使用してディレクトリを削除して所定の場所にbaz移動することもできます。しかし、これは退屈で命令がたくさんあります...別の慣習的でシンプルでエレガントな方法はありますか?

メモ:

  • 別の名前の競合がある場合は、オーバーライドmv(およびヒントを提供)の一般的な意味は問題ありません。しかし、その場合にはbazそうせずに失敗するだけです。

答え1

cd /var/foo/bar/baz
for src in *; do
    dest="${src}"
    suffix=0
    while [[ -e ../"${dest}" ]]; do
        dest="${src}.${suffix}"
        suffix=$((suffix+1))
    done
    mv -n "$src" ../"$dest"
done
cd ..
rmdir baz

かなりシンプルなソリューションです。現在のディレクトリから親ディレクトリにファイルを移動する準備をします。その名前のファイルがすでに存在する場合は、数字でサフィックスを追加します。ただし、次の番号は使用しないでください。返品何らかの理由で、すでにそこにあります。

この設定は、ディレクトリ、ソケット、一般ファイル、または他のすべての存在可能なものが呼び出されたエントリが存在する場合は[[ -e file ]]trueを返します。file

答え2

長すぎますが、次のように動作します。

cd /var/foo/bar
bazbaz_tmp_file=$(mktemp baz/XXXXXXXXXXXXXX)
[[ -e baz/baz ]] && mv baz/baz $bazbaz_tmp_file
mv baz/* .
rmdir baz
mv $(basename $bazbaz_tmp_file) baz

注:これは他のファイルを安全に移動できると仮定しますbaz/

関連情報