これはおそらく非常に単純ですが、わかりません。私はこのようなディレクトリ構造を持っています(dir2はdir1内にあります):
/dir1
/dir2
|
--- file1
|
--- file2
Dir2でなくdir1のfile1とfile2を取得するように、このダイレクタ構造を「フラット化」する最良の方法は何ですか。
GNU find
およびGNU mv
:
_find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +
_
基本的に、そのfind
がディレクトリツリー全体を通過し、最上位ディレクトリ(_-type f
_)にない各ファイル(_-mindepth 2
_)に対して動作する方法は、mv
を実行して移動します必要なディレクトリに(_-exec mv … +
_)。 mv
の_-t
_引数を使用すると、最初に宛先ディレクトリを指定できます。これは、_+
_形式の_-exec
_がすべてのソースの場所をコマンドの最後に配置するために必要です。 _-i
_は、重複を上書きする前にmv
を尋ねます。質問せずに_-f
_に置き換えることができます(要求しないか上書きしない場合は_-n
_)。
Stephane Chazelasが指摘するように、上記はGNUツール(Linuxでは標準ですが、他のほとんどのシステムではありません)でのみ機能します。以下は多少遅くなります(mv
を複数回呼び出すため)より普遍的:
_find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'
_
Zshの場合:
mv dir1/*/**/*(.D) dir1
**/
はサブディレクトリを再帰的にトラバースします。 glob qualifier.
は通常のファイルのみに一致し、D
はドットファイルが含まれることを保証します(デフォルトでは、名前が.
で始まるファイルはワイルドカード一致から除外されます)。空になったディレクトリを後でクリーンアップするには、rmdir dir1/**/*(/Dod)
を実行します。/
はディレクトリに制限され、od
は最初に一致深度を順序付けて、dir1/dir2/dir3
の前にdir1/dir2
を削除します。
ファイル名の全長が非常に長い場合、コマンドラインの長さが制限されることがあります。 Zshにはmv
とrmdir
のビルトインがあり、これらの制限の影響を受けません。これらを有効にするには、zmodload zsh/files
を実行します。
POSIXツールのみ:
find dir1 -type f -exec mv {} dir1 \;
find dir1 -depth -exec rmdir {} \;
または(ファイルごとに個別のプロセスを実行する必要がないため、より高速です)
find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
find dir1 -depth -exec rmdir {} +
tarとZipはどちらも、ディレクトリ構造を組み込んで削除する機能を備えているため、ネストされたディレクトリをすばやくフラット化できました。
tar -cvf all.tar *
次にall.tarを新しい場所に移動します。
tar -xvf all.tar --strip=4
これを試してください:
cp /dir1/dir2/file{1,2} /another/place
または、サブディレクトリのfile[0-9]*
に一致するファイルごとに:
cp /dir1/dir2/file[0-9]* /another/place
一緒に使用できる2つの関数を作成しました。そのために、-maxdepth $VAL
パラメータを追加して、ディレクトリレベルを制限できます。
# This scripts flattens the file directory
# Run this script with a folder as parameter:
# $ path/to/script path/to/folder
#!/bin/bash
rmEmptyDirs(){
local DIR="$1"
for dir in "$DIR"/*/
do
[ -d "${dir}" ] || continue # if not a directory, skip
dir=${dir%*/}
if [ "$(ls -A "$dir")" ]; then
rmEmptyDirs "$dir"
else
rmdir "$dir"
fi
done
if [ "$(ls -A "$DIR")" ]; then
rmEmptyDirs "$DIR"
fi
}
flattenDir(){
local DIR="$1"
find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
}
read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
flattenDir "$1" &
rmEmptyDirs "$1" &
echo "Done";
fi
同じ名前のファイルを含むディレクトリをフラット化するための使用例があったため、この質問に対する一般的な回答を拡張します。
dir1/
├── dir2
│ └── file
└── dir3
└── file
この場合、mv
に渡された-i
(--interactive
)オプションは、ディレクトリ構造をフラット化し、名前の競合を処理するための望ましい結果をもたらしません。したがって、単に--backup=t
に置き換えられます(--backup=numbered
と同等)。 https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options にある-b
(--backup
)オプションの詳細なドキュメント。
その結果:
find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +
収量:
dir1/
├── dir2
├── dir3
├── file
└── file.~1~