ファイルを含む複数のサブディレクトリがあるディレクトリがあります。
各ディレクトリのファイルを名前でアルファベット順に並べ替え、各ディレクトリの最初のファイルを指定された新しいディレクトリにコピーしたいと思います。
- 隠しファイルを無視したいです。
- ターゲットディレクトリに同じ名前のファイルがある場合は、両方のファイルを保存する必要があります。
サンプル:
parentdir
->dir1
->afile
->bfile
->cfile
->dir2
->dfile
->efile
->ffile
->dir3
->afile
->hfile
->ifile
次のように新しいディレクトリを入力するコマンドを実行したいと思います。
newdir
->afile
->afile.1
->dfile
これはどのように達成できますか?
答え1
最も簡単な方法は、コピー先を使用してls
ファイルを一覧表示することです。head
このbashスクリプトに示されているように:
for d in ./*/; do
src="$(ls "$d" | head -n 1)"
dstbase="newdir/$(basename "$src")"
if [[ ! -f "$dstbase" ]]; then
cp "$src" "$dstbase"
else
suffix=1
while [[ -f "$dstbase.$suffix" ]]; do
let suffix++
done
cp "$src" "$dstbase.$suffix"
fi
done
当然、それに応じてファイルパスを調整する必要があります。コピーするときなど、下のディレクトリを除外しようとするとdir1
問題が発生する可能性があるため、これは非常に脆弱です。dir2
また、未使用のファイル名を探すループに潜在的な競合状態があります。これはおそらく問題ではありませんが、複数のコピーを並列に実行するなどのことはしないでください。
答え2
これは次の行を使用して達成できます。
ls -ltr /parent_directory_path/ |
awk '$1~"^drw" {print $9}' |
while read line; do
ls -l $line |
awk '$1 ~ "^-r" {print $9}' |
head -1 |
awk -v line="$line" '{print "cp -rvfp" " " line"/"$1 " " "/newdir/" }';
done |
sh
答え3
zsh
GNUを使用するとcp
:
cd parentdir &&
for dir (*(/)) (cp --backup=numbered -- $dir/*(.[1]) newdir/)
--backup=numbered
ファイル名が指定されたバックアップスキームを実装しましたfile.~1~
。file.~2~
...したがって、最初のコピーが最後のコピーになりますfile.~max~
(順序を置き換えるには、file
リストを逆に処理する代わりに*(/On)
)。*(/)
POSIXlyでは、次のことができます。
cp_numbered() (
suffix=
n=0
while [ -e "$2$suffix" ] || [ -L "$2$suffix" ]; do
suffix=.$((n += 1))
done
exec cp -- "$1" "$2$suffix"
)
cd parentdir &&
for dir in */; do
for file in "$dir"/*; do
if [ -f "$file" ]; then
cp_numbered "$file" "newdir/${file#*/}"
continue 2
fi
done
done