Rsync 和 cp 命令将“.txt”文件复制到单个目录(仅当已存在时)

Rsync 和 cp 命令将“.txt”文件复制到单个目录(仅当已存在时)

我有一个目录结构,其中包含多个目录的多个.txt文件。我想将所有这些.txt文件复制到一个特定目录中。我在下面给出了我的目录结构:

Dir_1
    a.txt
    x.doc
    b.txt
Dir_2
    c.txt
Dir_3
    d.txt
    e.txt
    y.doc

要将所有.txt文件复制到目录中~/alltxt,我使用以下cp命令。

find . -name "*.txt" -exec cp {}  ~/alltxt/  \;

它工作得很好。现在我的目录alltxt如下所示。

alltxt
        a.txt
        b.txt
        c.txt
        d.txt
        e.txt

但我发现我只想将更改的.txt文件替换到该文件夹​​中。所以,我开始知道我可以使用rsync如下命令来做到这一点。

find .  -name '*.txt' -exec rsync -R {} ~/alltxt/ \;

但它会.txt 按文件夹复制文件,如下所示:

alltxt
  Dir_1
    a.txt
    x.doc
    b.txt
  Dir_2
    c.txt
  Dir_3
    d.txt
    e.txt
    y.doc

但是我怎样才能改变我的rsync命令,使其像我的命令一样工作呢cp

答案1

rsync有一个标志 ,--existing它将避免复制目标上尚不存在的文件:

find . -type f -name '*.txt' -exec rsync --existing {} "$HOME/alltxt/" ';'

我还添加了-type f确保find只找到常规文件,并且我已从中删除了-R标志 ( --relative),rsync因为我认为它在这种情况下没有用(使用此标志也是您获取目标上的子目录的原因)。我也使用$HOME而不是~因为我认为它看起来更好。

您可能还想在调用中添加-a( --archive)rsync以保留所有权和修改时间等。

类似的方法,但使用cp而不是rsync

find . -type f -name '*.txt' \
    -exec sh -c 'for n; do d="$HOME/alltxt/${n##*/}"; [ -f "$d" ] && cp "$n" "$d"; done' sh {} +

这会找到所有.txt文件并调用一个简短的 shell 脚本:

for n; do
    d="$HOME/alltxt/${n##*/}"
    [ -f "$d" ] && cp "$n" "$d"
done

该循环从 中获取许多.txt文件find。对于每个这样的名称n,它会在 中创建目标文件路径d,检查该路径是否引用现有的常规文件,如果是,则将给定文件复制到那里。

如果目标文件存在并且比找到的文件更旧,[ -f "$d" ]您可以使用该测试而不是测试。[ "$d" -ot "$n" ]这是一个非标准测试,但大多数 shell 都支持。

变量替换${n##*/}将从 中的路径中删除目录n,以便./some/path/file.txt将其变为file.txt(基本名称)。它可以被替换为$(basename "$n").

答案2

shopt -s globstar
cp --update --target-directory targetDirectory sourceRootDir/**/*.txt

在哪里:

  • shopt -s globstar设置扩展的通配选项,其中包括**模式
  • --target-directory-t给出要复制到的目标目录(也可以在所有参数的末尾指定,但将其放在脚本中通常更具可读性)。
  • --update或仅当目标较旧或不存在时才复制文件-ucp

相关内容