フォルダー内の4番目のファイルごとにコピーする方法


15

という名前のフォルダーに多くのファイルがあります00802_Bla_Aquarium_XXXXX.jpg。ここで、4番目のファイルごとにサブフォルダーにコピーする必要がありますselected/

00802_Bla_Aquarium_00020.jpg <= this one
00802_Bla_Aquarium_00021.jpg
00802_Bla_Aquarium_00022.jpg
00802_Bla_Aquarium_00023.jpg
00802_Bla_Aquarium_00024.jpg <= this one
00802_Bla_Aquarium_00025.jpg
00802_Bla_Aquarium_00026.jpg
00802_Bla_Aquarium_00027.jpg
00802_Bla_Aquarium_00028.jpg <= this one
00802_Bla_Aquarium_00029.jpg

どうすればいいですか?


の一部の出力で、superuser.com / q / 396536/87552のソリューションのようにできる場合がありますls。参照してくださいstackoverflow.com/q/4553751/789593 2行ごとについて質問。
NN

彼らは番号が付けられているとあなたが最後の番号がわかっている場合は、変動検討するかもしれないfor n in $(seq -w 20 4 200); do cp "00802_..._00${n}" ...; done
ウルリッヒ・シュワルツ

回答:


12

zshを使用すると、次のことができます。

n=0; cp 00802_Bla_Aquarium_?????.jpg(^e:'((n++%4))':) /some/place

POSIXly、同じ考え、もう少し冗長:

# put the file list in the positional parameters ($1, $2...).
# the files are sorted in alphanumeric order by the shell globbing
set -- 00802_Bla_Aquarium_?????.jpg

n=0
# loop through the files, increasing a counter at each iteration.
for i do
  # every 4th iteration, append the current file to the end of the list
  [ "$(($n % 4))" -eq 0 ] && set -- "$@" "$i"

  # and pop the current file from the head of the list
  shift
  n=$(($n + 1))
done

# now "$@" contains the files that have been appended.
cp -- "$@" /some/place

これらのファイル名には空白文字やワイルドカード文字が含まれていないため、次のこともできます。

cp $(printf '%s\n' 00802_Bla_Aquarium_?????.jpg | awk 'NR%4 == 1') /some/place

あなたは、POSIXのコードにもコメントを入れてくださいすることができます
ラーフルパティル

@ChrisDown for i doは標準であり、実際には移植性がfor i; doあり、定位置パラメーターをループする標準的な方法です。
ステファンシャゼル

7

bashでは、面白い可能性がありますが、ここではかなりうまく機能します。

cp 00802_Bla_Aquarium_*{00..99..4}.jpg selected

それは間違いなく最短かつ最も効率的な答えです。サブシェル、ループ、パイプ、awk病棟の外部プロセスはありません。1つのフォークcp(とにかく避けることはできません)と1つのbashブレース拡張とグロブ(所有しているファイルの数がわかっているので、完全に削除できます)。


4
…および2つの仮定:ファイルは連続して番号が付けられ、最初のファイルは4で割り切れます。
manatwork

@manatworkは、最初のものが4で割り切れない場合は問題ありませcp 00802_Bla_Aquarium_*{03..99..4}.jpg selected3 mod 4。(100が4で割り切れるという素晴らしい事実を使用しています)。現在、連続的に番号付けされたファイルについて、他のすべての答えは同じと仮定しています。
gniourf_gniourf

連続番号付けを前提とする他の回答はどれですか?ウルリッヒ・シュワルツのコメントだけを見つけましたが、そのような答えは見つかりませんでした。
マナトワーク

5

bashを使用するだけで、次のことができます。

n=0
for file in ./*.jpg; do
   test $n -eq 0 && cp "$file" selected/
   n=$((n+1))
   n=$((n%4))
done

パターン./*.jpgは、bash manが述べたように、アルファベット順にソートされたファイル名のリストに置き換えられるため、目的に合っているはずです。


bashでは、forループ内の3行を次の行に置き換えることができます(((++n)%4)) || cp "$file" selected/;-)。問題しかしあなたが上でフォークしているということであるcpため、各本当に効率的ではないファイル。
gniourf_gniourf

1

あなたがしている場合rubyインストールは、次のワンライナーを使用することができます。選択したディレクトリが存在することを前提としていることに注意してください。

ruby -rfileutils -e 'files = Dir.glob("*.jpg").each_slice(4) { |file| FileUtils.cp(file.first, "selected/" + file.first) }'

現在のディレクトリにある拡張子が.jpgのすべてのファイルのリストを取得して、4つの要素のリストにスライスし、各リストの最初の要素を現在のディレクトリで選択したディレクトリにコピーします。


1

ファイル名に改行がないことがわかっている場合は、次を使用できます。

find . -maxdepth 1 -name "*.jpg" | sort | while IFS= read -r file; do
  cp "$file" selected/
  IFS= read -r; IFS= read -r; IFS= read -r
done

@Gilles:編集してくれてありがとう。ただし、3回の読み取りでファイル変数を削除したのは、それらが必要ないことを指摘したいからです。
jfg956

1

GUIファイルマネージャーを使用して、5つのファイルごとに1行が占めるまでウィンドウの境界線のサイズを変更し、マウスを使用して最初の列を選択できます。


-1

@NNが言及したように1秒ごとにコピーするソリューションを提供するstackoverflow.com/q/4553751/789593を見ると、非常に簡単なソリューションは次のようになります。

  • 最初のファイルを開始フォルダーから削除します
  • 開始フォルダーから中間フォルダーに1秒ごとにコピーします
  • 1秒ごとに中間フォルダーから最終フォルダーにコピーします
  • 最初のファイルを手動で追加します

追加のコピーステップビットが必要なため、非常に効率的ではない場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.