次のファイル構造があります。
raw:
F1:
file1.pdf
F2:
file2.pdf
(...)
pdf:
(...)
フォルダごとに常に1つのPDFファイルのみがあり、ファイル/フォルダ名は任意に指定できます。
raw
ディレクトリ内のすべてのpdfファイルをpdfディレクトリにコピーし、そのファイル名をルートフォルダ名に変更したいと思います。上記の例では、結果は次のようになります。
raw:
F1:
file1.pdf
F2:
file2.pdf
(...)
pdf:
F1.pdf
F2.pdf
(...)
ワイルドカードのコピーについて読みましたが、ファイルをコピーするには2つのネストされたワイルドカードを使用する必要があるため、これは問題があるようです。したがって、これは明らかに機能しません。
cp raw/*/*.pdf pdf/*.pdf
この問題を解決する方法はありますか?それとも私のフォルダを繰り返し、正規表現を使ってパスを分割する必要がありますか?
答え1
コピーにワイルドカードを使用できます。ただし、ファイルをコピーするのではなく、ファイル名を変更する必要があります。つまり、各ファイルに新しい名前を割り当てる必要があるため、ループは避けられません。せいぜいループを実行するツールを使用できます。
perl-rename
(renamed
Debianベースのシステムから呼び出す)場合は、次のことができます。
$ rename -n 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
raw/F1/file1.pdf -> pdf/F1.pdf
raw/F2/file2.pdf -> pdf/F2.pdf
.pdf
これにより、これを行うのではなく、終わるすべてのファイル名を見つけることがraw
できます.pdf
。したがって、満足している場合は、実際にファイル名を変更せずにそのコマンドを実行してください。pdf/
-n
-n
rename 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
または、シェルループを使用できます。
for f in raw/*/*pdf; do
new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f");
echo "mv -- $f $new";
done
mv raw/F1/file1.pdf pdf/F1.pdf
mv raw/F2/file2.pdf pdf/F2.pdf
もう一度、うまくいけば、エコーを削除して実際にファイル名を変更します。
for f in raw/*/*pdf; do
new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f");
mv -- "$f" "$new";
done
重要:両方のソリューションがディレクトリごとに1つのファイルしかないと仮定しているため、競合は発生しません。同じサブディレクトリにあるすべてのファイルは同じ名前を持つため、追加のファイルが削除されます。
-i
各ツールのオプション(mv
an)を使用すると、rename
同じ名前のファイルを上書きする前に確認メッセージが表示されます。これにより解決策が作成されます。
rename -i 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
そして
for f in raw/*/*pdf; do
new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f");
mv -i -- "$f" "$new";
done
答え2
ネストしたループを使用します。
shopt -s nullglob # To prevent failures if there's no pdf in a dir.
for dir in raw/* ; do
for pdf in "$dir"/*.pdf ; do
cp -- "$pdf" pdf/"${dir#raw/}".pdf # Remove the "raw/" part
done
done
または、ファイルを繰り返してパラメータ拡張を2回適用してターゲット名を生成します。
for pdf in raw/*/*.pdf ; do
target=${pdf#raw/} # Remove the "raw/" part
target=${target%/*} # Remove the filename
cp -- "$pdf" pdf/"$target".pdf
done
答え3
そしてzsh
:
autoload -Uz zmv # best in ~/.zshrc
zmv -C 'raw/(*)/*.pdf' 'pdf/$1.pdf'