How to copy every 4th file in a folder

With zsh, you could do:

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

POSIXly, same idea, just a bit more verbose:

# 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

Since those filenames don't contain any blank or wildcard characters, you could also do:

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

In bash, a funny possibility, that will work rather well here:

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

That's definitely the shortest and most efficient answer: no subshell, no loop, no pipe, no awkward external process; just one fork to cp (that you can't avoid anyway) and one bash brace expansion and glob (that you can get rid of altogether since you know how many files you have).


Simply with bash, you can do:

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

The pattern ./*.jpg will be replaced by an alphabetically sorted list of file names as stated by the bash man, so it should fit your purpose.

Tags:

Bash

Cp

Files