Linux使用AWK输出的CP命令

4

我一直在努力学习Linux,今天早上专注于awk命令。我一直在尝试使用以下命令。

ls -lRt lpftp.* | awk '{print $7, $9}' | mkdir -p $(awk '{print $1}') | ls -lRt lpftp.* | cp $(awk '{print $9, $7}')

基本上,我正在尝试将目录中的每个文件移动到一个子目录中,该子目录基于该文件的最后修改日期。该命令首先仅打印我想要的文件,然后使用mkdir根据最后修改的日期创建一个文件夹。之后,我想做的是将每个文件移动到其关联的目录中,但由于现在的命令,它将每个文件都移动到01文件夹中,并打印出以下文本。
cp: 0653-436  12 is a directory.
    Specify -r or -R to copy.

每个目录只需一次。

有人知道我如何解决这个问题吗?或者是否有更好的方法?


你为什么要将 mkdir 的输出导入到 ls 中呢?mkdir 除了错误信息外不会产生任何输出,而 ls 也不会使用它的输入。 - Barmar
第二个LS语句的原因是,在mkdir之后,我无法从原始LS中访问文件名,因此我再次运行它以重新创建该列表。有更好的方法吗? - Cronisej
@Cronisej 是的,请看我的回答。 - eddiem
我理解你为什么有第二个ls语句。但我不理解的是,为什么你要把一些内容通过管道传递给它,而不是将其作为单独的命令运行。 - Barmar
虽然微小,但如果您使用两个独立的“ls”命令(无论是否正确执行),在技术上也存在竞态条件。例如,如果第一个文件在第一个“ls”命令完成后立即创建,会怎么样?然后,您将有一个“cp”命令排队等待将文件复制到不存在的目录中。最好是使用一个输出集来同时进行目录创建和文件复制。 - eddiem
显示剩余2条评论
2个回答

4

ls -lRt lpftp.* | awk '{print $7, $9}' | while read day file ; do mkdir -p "$day"; cp "$file" "$day"; done

这行命令中,dodone 之间的命令将会针对输出的每一行逐个执行。其中,awk 命令打印出的第一个参数将赋值给变量day ,第二个参数将赋值给变量file(每行一个)。在这里使用引号是不必要的,因为根据它们被设置的方式,这些变量中不会有空格。该命令实现的功能是:获取所有以“lpftp.”开头的文件,按照修改时间从最近到最早排序,并将每个文件复制到其最后修改日期所代表的目录下。如果目录不存在,则会创建它。

1

最安全,同时也是最快的方法是使用awk处理数据以输出一个shell脚本。在awk中,打印你期望执行的mkdircp命令。将结果通过管道传递给head(1),直到满意为止。也可以在less(1)中查看整个过程。然后按以下方式执行:

ls -lRg lpfpt.* | awk script.awk | sh -ex

那将把命令回显到标准错误输出,并在第一个错误时停止。如果您非常确定它是正确的,请省略 x 选项。
这种方法优于在 awk 中使用循环或一堆子进程(使用 system 函数),因为:
- 您可以看到将要发生的事情以及正在发生的事情 - 执行速度更快

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接