【问题标题】:How to copy folders and subfolders which have selected files如何复制已选择文件的文件夹和子文件夹
【发布时间】:2019-09-26 21:27:34
【问题描述】:

我有一个目录oridir,结构如下:

.
├── DIRA
│   ├── DIRA1
│   │   └── file2.txt
│   └── DIRA2
│       ├── file1.xls
│       └── file1.txt
└── DIRB
    ├── DIRB1
    │   └── file1.txt
    └── DIRB2
        └── file2.xls

我必须在保持目录结构的同时复制扩展名为.xls 的文件。所以我需要在newdir 文件夹中有以下目录和文件:

.
├── DIRA
│   └── DIRA2
│       └── file1.xls
└── DIRB
    └── DIRB2
        └── file2.xls

我尝试了以下命令,但它复制了所有文件和文件夹:

cp -r oridir newdir

可以通过以下方式查找所需文件:

$ find oridir | grep xls$
oridir/DIRB/DIRB2/file2.xls
oridir/DIRA/DIRA2/file1.xls

也如下:

$ find oridir -type f -iname *.xls
./oridir/DIRB/DIRB2/file2.xls
./oridir/DIRA/DIRA2/file1.xls

但是如何创建这些文件夹和复制文件。如何在 Linux 中使用 `bash' 实现这种选定的目录创建和复制文件?

编辑:一些文件和目录名称中也有空格。

【问题讨论】:

    标签: linux bash


    【解决方案1】:

    cp 的--parents 标志使用 DIRECTORY 下的完整源文件名

    例如,如果启用递归 glob ** (shopt -s globstar):

    cp --parents origin/**/*.xls target
    

    如果未启用递归 glob,则必须为目录层次结构的每个级别添加通配符:

    cp --parents origin/*/*/*.xls target
    

    【讨论】:

    • 如果原始文件夹是oridir,新文件夹是newdir,命令是什么?
    • 使用命令:$ cp --parents oridir/**/*.xls newdir 我得到错误:cp: failed to get attributes of 'oridir/**': No such file or directory
    • 听起来你需要 shopt -s globstar -- 递归 glob ** 没有开箱即用。
    【解决方案2】:

    如果目标目录是“dest”。

    foo.sh

    #!/bin/bash
    dest=./dest
    find . -type f -name "*.xls" | while read f
    do
        d=$(dirname "${f}")                                                         
        d="${dest}/${d}"
        mkdir -p "${d}"
        cp "${f}" "${d}"
    done
    

    制作目录和文件。

    $ mkdir -p DIRA/DIRA1
    $ mkdir -p DIRA/DIRA2
    $ mkdir -p DIRB/DIRB1
    $ mkdir -p DIRB/DIRB2
    $ touch DIRA/DIRA1/file2.txt
    $ touch DIRA/DIRA2/file1.xls
    $ touch DIRA/DIRA2/file1.txt
    $ touch DIRB/DIRB1/file1.txt
    $ touch DIRB/DIRB1/file2.xls
    

    结果是

    $ find dest
    dest
    dest/DIRB
    dest/DIRB/DIRB1
    dest/DIRB/DIRB1/file2.xls
    dest/DIRA
    dest/DIRA/DIRA2
    dest/DIRA/DIRA2/file1.xls
    

    【讨论】:

    • 是的,它有效。如果你能解释它是如何工作的,那就太好了。
    • "find" 为您制作所有文件。 "d=..." 从 "find" 结果生成目标目录路径。 “mkdir”制作目录。 "cp" 复制文件。
    • 您应该在上面的答案中添加此内容。但是,如果目录名称中有任何空格,您的解决方案将不起作用。如果目录名称是 DIR A 而不是 DIRA,则它不起作用。如何纠正?
    • 已修复。这样可以吗?
    • 是的,它有效。您应该在回答中说明您是如何纠正这个问题的。
    【解决方案3】:

    先看Yuji的精彩回答,不过我觉得tar这里也是一个不错的选择:

    cd oridir; find . -name "*.xls" | xargs tar c | (cd ../newdir; tar x)
    

    您可能需要根据目录的精确路径调整oridir 和/或../newdir

    可能的改进:这是一个更好的版本,它可以处理名称中带有空格(或其他奇怪字符)的文件(和路径),并且使用 tar 自己的选项而不是 @987654326 @和cd

    cd oridir; find . -print0 -name "*.xls" | tar -c --null -T- | tar -C ../newdir -x
    

    解释:

    -print0--null 导致各自的命令仅通过空 (ASCII 0) 字符分隔文件名。

    -T- 导致tar 从标准输入读取文件名。

    -C 在提取之前将tar 转换为cd

    【讨论】:

    • tar的有趣用法!
    • 如果文件名有空格,它将不起作用。它被分成 2 个文件名。
    • 试试我几分钟前添加的“改进”版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多