创建硬链接而不是使用 rsync 复制文件

创建硬链接而不是使用 rsync 复制文件

以下命令递归地查找包含foo(但不包含bar)的所有文件,并保留目标目录中的目录结构,例如,如果我有/path/to/2017/foo.ps,它会在包含resp 的目录下/path/to/2018/foo.pdf创建子目录2017和。。2018~/path/to/dir/foo.psfoo.pdf

find . -iname \*foo\*pdf -exec rsync -R --exclude='*bar*' {} ~/path/to/dir/ \;

这个命令相当于什么,这样我最终得到的是硬链接而不是副本?

答案1

由于没有其他人这样做,为了回答标题问题,您可以使用--link-dest.一般来说,如果您想使用 rsync 同步s/d/使用硬链接而不是副本,您可以执行以下操作:

rsync -r --link-dest="$PWD/s/" s/ d/

根据您的具体需求,您想要指定文件而不是整个目录,您可以执行以下操作:

find . \
  -iname \*foo\*pdf \
  -exec bash -c '
    rsync -R \
      --exclude="*bar*" \
      --link-dest="$PWD/$(dirname "$1")" \
      "$1" \
      ~/path/to/dir/
  ' sh {} \;

这里之所以引入bash,是为了能够获取dirname文件路径的。--link-dest需要目录而不是文件本身。我也使用$PWD因为--link-dest是相对于目标目录,而不是当前目录。

答案2

这看起来不太像 rsync 的工作。 Rsync 对于递归复制最有用,但显然您只想复制常规文件。rsync这里的唯一优点cp是它根据需要创建父目录。您可以使用一个小的 shell 脚本调用mkdir来完成此操作。

find . -type f -iname '*foo*.pdf' ! -name '*bar*' \
       -exec sh -c 'mkdir -p "~/path/to/dir/${0%/*}" && cp "$0" ~/path/to/dir/"$0"' {} \;
  • 添加-type ffind命令中以排除非常规文件(例如目录)。还用于-xtype f处理常规文件的符号链接。
  • ! -name '*bar*'相当于 rsync--exclude选项。
  • sh -c '…' {}执行 shell 脚本,并将$0其设置为 . 找到的文件名find
  • mkdir -p …根据需要创建目标目录和任何父目录。

在这里您可以替代ln创建cp硬链接。


或者你可以使用桀骜zmv功能。在 zsh 中:

setopt extended_glob
autoload zmv
mkdir_ln () {
  mkdir -p -- $2:h
  ln -- $1 $2
}
zmv -p mkdir_ln '**/(#i)*foo*.pdf~**/*bar*' ~/path/to/dir/'$f'
  • zmv -p mkdir_ln PATTERN REPLACEMENT调用每个匹配的,并将in替换为。mkdir_ln FILENAME REPLACEMENTFILENAMEPATTERN$fREPLACEMENTFILENAME
  • mkdir -p -- $2:h$2根据需要创建目录部分和任何父目录。
  • **/…递归匹配子目录中的文件。
  • (#i)开始不区分大小写的匹配。
  • ~**/*bar*排除名称包含bar.

答案3

听起来像是一份工作pax

find . -iname '*foo*pdf' ! -name '*bar*' -print0 |
  pax -0rwl ~/path/to/dir/

如果您pax不支持非标准-0,请删除0from -print0-0rwl但请注意,如果您的文件路径包含换行符,则它将无法正常工作。

如果您没有pax(POSIX,但不是 GNU),请尝试替换为cpio -0pd(GNU,但不是 POSIX)。

相关内容