yae*_*ael 2 linux bash find rsync shell-script
在/home文件夹下,我们有许多子文件夹,如下所示:
/home/user1
/home/user2/user_sub_2
/home/user3/user_sub_3/info_sub
/home/user4/INFO_FOLDER
Run Code Online (Sandbox Code Playgroud)
我们要/home递归地将 下的所有文件复制到该/tmp/calculation文件夹中。所有文件都应直接放入目标文件夹(不应创建子目录)。如果两个或多个文件具有相同的名称,则应将最近修改的文件复制到/tmp/calculation.
执行此操作的正确方法是什么?
find /home ! -type d -exec bash -c '
for pathname do
if [ "$pathname" -nt "/tmp/calculation/${pathname##*/}" ]
then
cp "$pathname" /tmp/calculation
fi
done' bash {} +
Run Code Online (Sandbox Code Playgroud)
这将在 下找到所有非目录文件/home,对于这些文件的批处理,它将调用一个简短的bash脚本。
短bash脚本将遍历当前批次的路径名,并且对于每个路径名,将测试-nt当前文件是否比目标目录中的副本新(或者那里是否不存在副本)。如果目标目录中的文件较旧或不存在,cp则用于将当前文件复制到目标目录。
参数扩展${pathname##*/}将删除实际文件名之前的任何目录路径,只留下路径名的文件名部分。可以用 代替$(basename "$pathname")。
有关的:
大多不相关:
该-nt测试为非标准测试。这就是为什么我选择使用bash用于find调用的内部脚本。使用sh -c代替bash -c可能会起作用,但测试的语义可能在可能伪装为 的shell 之间略有不同sh。
例如,在bash,zsh和kshshell 中,-nt如果第一个操作数具有比第二个操作数更新的修改时间戳,或者如果第二个操作数不存在,则测试为真。
dash然而,在shell 中,这两个文件大部分都存在,并且第一个文件必须比第二个文件更新才能使测试为真(根据文档)。在这种情况下,这种差异不会成为问题。
在yashshell 中,手册中没有指定如果任一文件不存在会发生什么。
因此,在使用非标准工具时使用特定 shell 是最安全的,即使在这种特定情况下,它可能sh -c无论如何都可以使用。
(在这种情况下使用的缺点bash是它在比较的时间戳中只有一秒的分辨率,但这是另一回事)