【问题标题】:How do I move a file from a directory containing a specific number into a different directory?如何将包含特定数字的目录中的文件移动到不同的目录中?
【发布时间】:2019-11-12 08:46:21
【问题描述】:

我想将编号为 1995、1996 和 1997 的文件夹中的所有文件移动到不同的文件夹中。

我在此列表中找到的大部分内容都与移动包含任何模式的任何文件有关。我希望命令在目录中查找,扫描 .txt 文件的内容,一旦找到 1996,就将其放入 1996 目录中。

这意味着如果该命令在目录中查找,扫描 .txt 文件,并在第一行找到 1996 并在第十行找到 1995,它不会将文件放在 1996 和 1995 文件夹中。我希望它只将文件放在 1996 文件夹中。

grep -rl --null --include '*.txt' 1996 . | xargs -0 sh -c 'cp "$@" /folderpath' sh

这似乎将 1995 文件放入 1996 文件夹中,只是因为它在文件的某处包含 1995。

【问题讨论】:

  • 我不明白。第一个文件包含什么?所以我得到的是:1)对于目录中的每个文件 2)您要检查文件是否在第一行包含数字 1995 3)如果包含,请将其放入 1995 文件夹中 4)重复步骤 2 和 3数字 1996 和 1997。对吗?
  • 是的,你是对的。

标签: shell command-line grep xargs


【解决方案1】:

我认为这样的事情可能会奏效:

find . -name '*.txt' -print0 |
xargs -0 -n1 sh -c '
    if a=$(head -n1 "$1" | grep -o "199[567]"); then
        mv "$1" "./$a"
    fi
' --

或者,xargs 可以替换为 while IFS= read -r file; do 循环。看起来像:

find . -name '*.txt' -print0 |
while IFS= read -r file; do
    if a=$(head -n1 "$file" | grep -o "199[567]"); then
        mv "$file" "./$a"
    fi
done
  • find 找到一切
    • . - 在当前目录中
    • -name '*.txt' - 名称以 .txt 结尾
    • -print0 - 并将它们打印为零终止列表
  • | - 管道,将一个命令的输出传递给另一个
  • while - 执行 do ... done 正文,直到命令返回非零退出状态
  • IFS= read -r file - 读取零分隔列表的流行助记符,请参阅 bashfaq How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
    • head -n1 "$file" - 从文件中提取第一行
    • grep
      • -o - 只输出匹配的字符串
      • 199[567] - 匹配 1995 或 1996 或 1997
      • grep 如果匹配成功则输出零退出状态(在if 很重要)
    • a=$(...) - 将命令的输出分配给a。进程替换$(...) 的退出状态是最后执行的命令,在本例中为grep。
    • if command - 仅当命令以非零退出状态返回时才执行 then ... fi 正文。 IE。此处仅当 grep 成功匹配字符串时,才会返回零退出状态。
      • mv "$file" "./$a" - 变量 a(错误命名...)包含 grep 匹配的字符串,因此它将是 1995 或 1996 或 `1997。所以将文件移动到正确的文件夹。

【讨论】:

  • 我应该把新的文件路径放在哪里?是每个引用“1”都引用第一行,还是只引用“$1”?
  • 1) man find 替换路径中的 . 点。 2)我不明白,你可以测试一下。 echo 1 | xargs -n1 sh -c 'echo "$1"' --我不明白什么是“对“1”的引用”或对 $1 的引用?您可以将-t 选项添加到xargs 以进行调试。
  • 所以说我想在文件的每 3 行找到 1996。我输入find . -name '*.txt' -print0 | xargs -0 -n3 sh -c ' if a=$(head -n3 "$3" | grep -o "1996"); then mv "$3" "/$a" fi ' --
  • 请阅读文档。 man head man xargs xargs -n3 一次将 3 个文件传递到 sh,你想为每个文件运行它,所以 -n1。 head -n3 将提取前 3 行。你可以做head -n3 "$1" | tail -n1 只提取第三行。使用while read 循环而不是 xargs 可能更容易让您看到它,所以我编辑了答案。
  • 我也添加了一些解释。
猜你喜欢
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-29
相关资源
最近更新 更多