【问题标题】:Copying a type of file, in specific directories, to another directory将特定目录中的一种文件复制到另一个目录
【发布时间】:2020-02-11 20:47:11
【问题描述】:

我有一个包含目录列表的 .txt 文件。我想制作一个通过此 .txt 文件的脚本,将列出的特定文件类型的目录中的任何内容复制到另一个目录。

我从来没有对目录做过这个,只有文件。

如何编辑这个简单的脚本来读取目录列表、查找 .csv 文件并将其复制到另一个目录?

cat filenames.list | \
while read FILENAME
do
  find . -name "$FILENAME" -exec cp '{}' new_dir\;
done

【问题讨论】:

  • @请准确地说:它应该对目录列表中的目录做什么?例如,它是否应该在您的$PWD 下搜索此类目录?还是应该在这些目录中搜索?举个例子,并展示你自己解决问题的尝试。
  • 你能描述一下预期的输出吗?假设 dir1/file1.csv 存在,您希望将文件复制到 dest/file1.csv 还是 dest/dir1/file1.csv ?从问题来看,您似乎正在尝试将树“展平”到一个文件夹中。

标签: linux bash shell cp


【解决方案1】:
for DIRNAME in $(dirname.list); do find $DIRNAME -type f -name "*.csv" -exec cp \{} dest \; ; done;

对不起,在我的第一个答案中,我不明白您的要求。 第一行代码,简单地,将目录列表中的 dirname 条目作为路径,并在其中搜索每个以“.csv”扩展名结尾的文件;然后将其复制到您想要的目的地中。 但是你可以用更少的代码来做:

for DIRNAME in $(dirname.list); do cp $DIRNAME/*.csv dest ; done

【讨论】:

  • 您能否详细说明您的答案,也许通过解释发生了什么?
  • 这怎么可能?
【解决方案2】:

尽管有filenames.list 列表的文件名,让我假设该文件包含目录名列表,而不是文件名。那你试试看:

while IFS= read -r dir; do
    find "$dir" -type f -name "*.mp3" -exec cp -p -- {} new_dir \;
done < filenames.list

find 命令在“$dir”中搜索扩展名为.mp3 的文件,然后将它们复制到new_dir
上面的脚本不关心文件名的重复。如果您想保留原始目录树和/或需要针对文件名重复的对策,请告诉我。

【讨论】:

    【解决方案3】:

    在 while 循环中使用 find 有效,但 find 将在文件的每一行运行,另一种选择是将列表保存在数组中,这样 find 可以在一次搜索中搜索列表中的目录。

    如果你有 bash4+,你可以使用 mapfile。

    mapfile -t directories < filenames.list
    

    如果你被 bash3 卡住了。

    directories=()
    while IFS= read -r line; do
      directories+=("$lines")
    done < filenames.list
    

    现在,如果您只是追求一种文件类型,例如以 *.csv 结尾的文件。

    find "${directories[@]}" -type f -name '*.csv' -exec sh -c 'cp -v -- "$@" /newdirectory' _ {} +
    

    如果您有多个文件类型要匹配并且多个目录要复制文件。

    while IFS= read -r -d '' file; do
      case $file in
        *.csv) cp -v -- "$file" /foodirectory;;  ##: csv file copy to foodirectory
        *.mp3) cp -v -- "$file" /bardirectory;;  ##: mp3 file copy to bardirectory
        *.avi) cp -v -- "$file" /bazdirectory;;  ##: avi file copy to bazdirectory
      esac
    done < <(find "${directories[@]}" -type f -print0)
    

    find 的 print0 将与 read 的 -d '' 一起处理带有空格和换行符的文件。见How can I find and deal with file names containing newlines, spaces or both?

    -- 在那里,所以如果您有一个以破折号开头的有问题的文件名 - cp 不会将其解释为 option

    【讨论】:

      【解决方案4】:

      鉴于 find 能够处理多个文件夹,并假设目标是将所有 csv 文件“展平”到一个目标中,请考虑以下事项。

      请注意,它假定文件夹名称没有特殊字符(包括空格、制表符、换行符等)。

      作为一个附带好处,它将最大限度地减少“cp”调用的数量,从而使处理在大量文件/文件夹中高效。

      find $(<filename.list) -name '*.csv' | xargs cp -t DESTINATION/
      

      对于更复杂的情况,文件夹名称/文件名称可以是任何内容(包括空格、'*' 等),请考虑使用 NUL 分隔符(-print0 和 -0)。

      xargs -I{} -t find '{}' -name '*.csv' <dd -print0 | xargs -0 -I{} -t cp -t new/ '{}'
      

      这将分叉多个find 和多个cp

      【讨论】:

      • 太好了,xargs 是赢家!
      猜你喜欢
      • 2012-02-15
      • 2019-12-08
      • 2017-11-18
      • 2013-06-01
      • 2020-06-22
      • 2014-08-12
      • 2013-10-24
      • 2011-10-24
      相关资源
      最近更新 更多