【问题标题】:Copying a file into multiple directories in bash将文件复制到bash中的多个目录中
【发布时间】:2018-07-04 13:51:25
【问题描述】:

我有一个文件我想复制到大约 300,000 个不同的目录中,这些目录本身被分成两个目录,例如

DirA/Dir001/
...
DirB/Dir149000/

但是当我尝试时:

 cp file.txt */*

返回:

bash: /bin/cp: Argument list too long

当您有太多需要使用 cp 的文件时,将文件复制到多个目录的最佳方法是什么?

【问题讨论】:

  • 你到底为什么要制作 300,000 个 Python 脚本文件的副本?请更详细地说明您要解决的问题;几乎肯定有更好的方法。
  • cp 只有一个参数可以是目标目录; cp one two three 会将onetwo 复制到three,覆盖one 的副本。
  • @Manuel:不是重复的; OP 已经发现 cp 无法做到这一点,并要求对其进行 alternatives —— 而该链接问题的答案atrociously 很糟糕。 (echols 通过管道传送到 xargs真的吗?文件名中有一个空格,你的“解决方案”会中断......)
  • @Neosage:你的问题就是我们所说的“XY 问题”。您要求解决问题 Y,但由于问题 X,您只有 拥有。您应该要求我们解决问题 X(您的脚本需要在与它操作的文件相同的目录)。也许在不同的问题? ;-)

标签: bash


【解决方案1】:

问题的答案是find

find . -mindepth 2 -maxdepth 2 -type d -exec cp script.py {} \;

当然@triplee 是对的……为什么要复制这么多文件?

当然,您可以创建文件的链接...

find . -mindepth 2 -maxdepth 2 -type d -exec ln script.py {} \;

选项-mindepth 2 -maxdepth 2find 的递归搜索限制为恰好 距当前目录(.) 两级深处的元素。 -type d 匹配所有目录。 -exec 然后对找到的每个元素执行命令(直到结束 \;),将 {} 替换为元素的名称(两级深度子目录)。

创建的链接是硬链接。这意味着,您在一处编辑脚本,该脚本在所有 处看起来会有所不同。出于所有意图和目的,该脚本在所有地方,其中没有一个比其他的更“真实”。 (这个概念可能会让那些不习惯它的人感到惊讶。)如果您想创建“软”链接,请使用ln -s,这些链接只是对原始位置中“唯一的,真实的”script.py 的引用。

find ... -exec ... {} 的美妙之处在于,与许多其他方法相比,它可以正常工作,即使对于其中包含“有趣”字符的文件名,包括但不限于空格或换行符。


但是,您实际上应该只需要 一个 脚本。您应该在每个目录中修复需要该脚本的项目部分; 是损坏的部分......

【讨论】:

    【解决方案2】:

    your other question 的答案推断,您的代码似乎类似于

    for TGZ in $(find . -name "file.tar.gz")
    do
        mkdir -p work
        cd work
        tar xzf $TGZ
        python script.py
        cd ..
        rm -rf work
    done
    

    当然,微不足道的解决方法是替换

    python script.py
    

    python ../script.py
    

    瞧,您不再需要每个目录中的脚本副本。

    我会进一步建议重构 cd 并更改 script.py,以便您可以将目录传递给它以作为命令行参数进行操作。 (简而言之,import sys 并检查 sys.argv[1] 的值,尽管您经常希望有选项解析和对多个参数的支持;来自 Python 标准库的 argparse 有点吓人,但有友好的第三方包装器比如click。)

    顺便说一句,许多初学者似乎认为可执行文件的位置将是执行时的工作目录。显然不是这样。或/bin/ls 只会列出/bin 中的文件。

    为了摆脱评论中提到的cd 问题,一个最小的修复是

    for tgz in $(find . -name "file.tar.gz")
    do
        mkdir -p work
        tar -C work -x -z -f "$tgz"
        (cd work; python ../script.py)
        rm -rf work
    done
    

    同样,如果您可以更改 Python 脚本,使其不需要当前目录中的输入文件,这可以进一步简化。还要注意变量小写的偏好,以及在包含文件名的变量周围使用引号。在命令替换中使用 find 仍然有些问题(它不适用于包含空格或 shell 元字符的文件名)但也许这是一个单独问题的主题。

    【讨论】:

    • 不幸的是我遇到了这个问题:gzip: ./archaea/GCF_900111935.1/GCF_900111935.1_IMG-taxon_2617270732_annotated_assembly_protein.faa.gz: No such file or directory 运行脚本时:for GZ in $(find . -name "*.gz") do mkdir -p work cd work gunzip $GZ python3 ../propgenfromproteome.py cd .. rm -rf work done 我不太明白,因为这些文件肯定存在!编辑:我正在开发一个使用 sys 的 v2,但我觉得对于这个特定的脚本可能需要大量修改
    • cd 正是这里的问题;循环正在接收与cd 之前的目录相关的文件名。
    • 那么解决方案本质上是重写脚本吗?
    猜你喜欢
    • 2012-07-31
    • 2017-08-14
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 2020-12-08
    相关资源
    最近更新 更多