如何复制文件夹中的每个第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,它询问第二行。
NN

如果已编号并且您知道最后一个编号,则可以考虑采用for n in $(seq -w 20 4 200); do cp "00802_..._00${n}" ...; done
Ulrich Schwarz

Answers:


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它更具便携性,并且是循环遍历位置参数的规范方法。
斯特凡Chazelas

7

在bash中,这是一种有趣的可能性,在这里效果很好:

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

这绝对是最短,最有效的答案:没有子shell,没有循环,没有管道,没有awk病房外部进程;只需一个分支cp(无论如何都无法避免)和一个bash括号扩展和glob(因为您知道有多少文件,因此可以完全摆脱它)。


4
... 2个假设:文件编号连续,并第一个是分割与4
manatwork

@manatwork如果第一个不能被4整除则没问题:例如,cp 00802_Bla_Aquarium_*{03..99..4}.jpg selected如果需要3 mod 4。(我使用的奇妙事实是100被4整除)。现在,关于连续编号的文件,所有其他答案都假定相同。
gniourf_gniourf 2012年

哪些其他答案采用连续编号?我只找到Ulrich Schwarz的评论,而没有这样的答案。
manatwork 2012年

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循环可以只用这条线来代替:(((++n)%4)) || cp "$file" selected/;-)。但是,问题是您cp每个文件分叉了,这并不是很有效。
gniourf_gniourf 2012年

1

如果已ruby安装,则可以使用以下单线。请注意,它假定所选目录存在。

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

它获取当前目录中所有扩展名为.jpg的文件的列表,并将其切成四个元素的列表,然后将每个列表中的第一个元素复制到当前目录中所选的目录中。


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

@吉尔斯:感谢您的编辑。我在读取的3中删除了文件变量,因为我想指出它们是不需要的。
jfg956

1

您可以使用GUI文件管理器并调整窗口边框的大小,直到每5个文件占据一行,然后使用鼠标选择第一列...


-1

看一下stackoverflow.com/q/4553751/789593,它提供了一种解决方案,可以复制@NN提到的每一秒,一个非常简单的解决方案是:

  • 从起始文件夹中删除第一个文件
  • 将第二个文件夹从起始文件夹复制到中间文件夹
  • 将每一秒钟从中间文件夹复制到最终文件夹
  • 手动添加第一个文件

它可能不是很有效,因为它需要一个额外的复制步骤,这应该很容易做到。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.