命令Linux从指定工作日开始拷贝文件



我正在计算一个命令来复制在星期六修改的文件。

find -type f -printf '%Tat%pn'

这样行以工作日开始。

当我将它与使用正则表达式(以"za"开头)的"egrep"命令结合使用时,它只显示以"za"开头的文件。

find -type f -printf '%Tat%pn' | egrep "^(za)"

("za"是荷兰语"zaterdag"的缩写,意思是星期六,

现在我想用下面的命令复制这些文件:

find -type f -printf '%Tat%pn' -exec cp 'egrep "^(za)" *' /home/richard/test/ ;

不幸的是它不起作用。

有什么建议吗?

当前的问题是-printf-exec是相互独立的。您想要处理-printf的结果来决定是否实际运行-exec部分。当然,在单引号中传递表达式只是传递一个静态字符串,并不以任何方式对表达式求值。

对求值问题的直接修复是使用命令替换而不是单引号,但是-printf函数的结果对命令替换不可用的问题仍然存在(无论如何,命令替换将在find运行之前发生,而不是在它运行时发生)。

一个常见的解决方法是将shell脚本片段传递给-exec,但这仍然不会将-printf函数暴露给-exec部分。

find whatever -printf whatever -exec sh -c '
    case $something in za*) cp "$1" "$0"; esac' "$DEST_DIR" {} ;

所以我们必须想出一个不同的方法来传递$something

(上面使用了一个便宜的技巧将$DEST_DIR的值传递给子shell,这样我们就不必对它进行exportsh -c ...的第一个参数结束于$0。)

这里有一个比较迂回的方法来完成这个任务。我们创建了一个格式字符串,它可以传递给sh进行计算。为了避免麻烦的文件名,我们打印匹配文件的inode号,然后将它们传递给find的第二个实例来执行实际的复制。

find ( -false $(find -type f 
      -printf 'case %Ta in za*) printf "%%s\n" "-o -inum %i";; esacn' |
    sh) ) -exec cp -t "$DEST_DIR" +

使用索引节点号意味着可以正确处理任何文件名(包括包含换行符、单引号或双引号等的文件名),但可能会显著增加运行时间,因为我们需要两次运行find。如果你有一个大的目录树,你可能会想要重构它,为你的特定场景(可能只运行在当前目录,并创建一个包装器,在每个目录中运行它,你想检查…在这里大声思考;我不确定它是否真的有帮助)。

这使用了GNU find的特性,这些特性在*BSD(包括OSX)中是不可用的。

你能做的就是展开shell。就像

cp $(find -type f -printf '%Tat%pn' | egrep "^(za)") $DEST_DIR

假设您的findgrep的结果只是文件名(以及完整路径),这将复制所有符合您的标准的文件到您设置的$DEST_DIR

EDIT正如在注释中提到的,如果文件名包含空格,这将不起作用。如果是这种情况,您可以这样做:

find -type f -printf '%Tat%pn' | egrep "^(za)" | while read file; do cp "$file" $DEST_DIR; done

最新更新