以下命令递归地查找包含foo
(但不包含bar
)的所有文件,并保留目标目录中的目录结构,例如,如果我有/path/to/2017/foo.ps
,它会在包含resp 的目录下/path/to/2018/foo.pdf
创建子目录2017
和。。2018
~/path/to/dir/
foo.ps
foo.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 f
到find
命令中以排除非常规文件(例如目录)。还用于-xtype f
处理常规文件的符号链接。 ! -name '*bar*'
相当于 rsync--exclude
选项。sh -c '…' {}
执行 shell 脚本…
,并将$0
其设置为 . 找到的文件名find
。mkdir -p …
根据需要创建目标目录和任何父目录。
在这里您可以替代ln
创建cp
硬链接。
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 REPLACEMENT
FILENAME
PATTERN
$f
REPLACEMENT
FILENAME
mkdir -p -- $2:h
$2
根据需要创建目录部分和任何父目录。**/…
递归匹配子目录中的文件。(#i)
开始不区分大小写的匹配。~**/*bar*
排除名称包含bar
.
答案3
听起来像是一份工作pax
:
find . -iname '*foo*pdf' ! -name '*bar*' -print0 |
pax -0rwl ~/path/to/dir/
如果您pax
不支持非标准-0
,请删除0
from -print0
,-0rwl
但请注意,如果您的文件路径包含换行符,则它将无法正常工作。
如果您没有pax
(POSIX,但不是 GNU),请尝试替换为cpio -0pd
(GNU,但不是 POSIX)。