执行 for 循环管道的任何简单方法,例如 ` ls | grep ".*.7z" | grep ".*.7z" | grep ".*.7z" | 7z -e {}`

Mit*_*ril 5 command-line bash scripts

我很好奇是否有一个函数/命令来处理循环管道?

\n\n

很容易出现低于需求的情况

\n\n
    \n
  1. 您运行命令返回多行
  2. \n
  3. 你需要处理每一行
  4. \n
  5. 将每一行传递给另一个函数/命令
  6. \n
\n\n

例如:

\n\n

您需要找到一些与模式匹配的路径,将每个路径移动到另一个地方:

\n\n
# 1.\nfind path_A -name \'*AAA*\' -exec mv -t path_B {} +\n\n# 2.\nfind path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B \n
Run Code Online (Sandbox Code Playgroud)\n\n

人们会感到困惑,

\n\n
    \n
  1. 为什么需要 mv -t(我的意思是,通过 [for 循环管道] 你可以使用mv {} some_path \xef\xbc\x8cjust like what you wrote without pipe )
  2. \n
  3. 为什么执行或 | xargs就是这样写的,xargs需要更多的选项,但实际上在许多计算机语言中不需要\xe3\x80\x82
  4. \n
  5. 为什么我不能使用 ls ... mv -t path_B {} + ,或者ls | xargs -0 -I {} mv {} path_B换句话说,为什么我更改为另一个命令后它不起作用?
  6. \n
  7. 为什么我在更改mv7z: 时失败find path_A -name \'*AAA*\' -exec 7z -t {} +
  8. \n
\n\n

注意:以上不是问题,只是示例!

\n\n
\n\n

我问这个问题是为了寻求一种常见且简单的方法来应对循环管道。\n是否有一种简单而常见的方法可以做到:

\n\n
# 0\ncommand with option (usually you use a command like this)\n\n# 1\ncommand with option [for loop pipe] command with option | command with option\n# 2\ncommand with option [for loop pipe] command with option | command with option [for loop pipe] command with option\n# 3 \n....\n
Run Code Online (Sandbox Code Playgroud)\n\n

command with option 因此,当您使用 [for Loop Pipe] 时,不需要进行更改。这样对于日常使用来说会方便很多。

\n\n

更新

\n\n

我举的所有例子只是想说,当不同的命令有自己的风格来处理多行输入时,正常的方式会令人困惑,它需要execxargs或其他一些选项。如果我们有一个for pipe 命令可以使用选项连接两个命令。使用起来会很方便

\n\n

我的意思是,如果您使用高级语言。例如蟒蛇,

\n\n
# 0\ncommand with option (usually you use a command like this)\n\n# 1\ncommand with option [for loop pipe] command with option | command with option\n# 2\ncommand with option [for loop pipe] command with option | command with option [for loop pipe] command with option\n# 3 \n....\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是一个非常简单的示例,有很多缺陷,但它解释了我试图在 bash 命令中获取的内容。

\n

pa4*_*080 3

我不确定这是否是对这个问题的直接回答(问题不止一个),但我认为您要求的是以下内容:

\n
    \n
  • for使用命令替换循环或
  • \n
  • while循环与进程替换
  • \n
\n
\n

for循环与$(command substitution)

\n

命令替换允许命令的输出替换命令本身。for我们可以通过这种方式将此功能与循环结合起来:

\n
for item in "$(find . -type f)"\ndo\n    echo "$item" | tee -a ./"file-list.txt"\ndone\n
Run Code Online (Sandbox Code Playgroud)\n
\n

while循环与<(process substitution)

\n

进程替换允许使用文件名引用进程\xe2\x80\x99s的输入或输出。我们可以while借助内置函数将此功能与循环结合起来read,如下所示:

\n
while IFS= read -r item\ndo\n    echo "$item" | tee -a ./"file-list.txt"\ndone < <(find . -type f)\n
Run Code Online (Sandbox Code Playgroud)\n

在最后一部分中< <(find . -type f),第一个<表示当前的标准输入loop,并将<(find . -type f)被视为文件。有关构造的更多信息,IFS= read -r line您可以阅读St\xc3\xa9phane Chazelas 的这篇精彩文章

\n

您可以通过使用管道而不是进程替换来实现与上述相同的效果(但不首选此选项,因为它可能会导致错误):

\n
find . -type f | while IFS= read -r file\ndo\n    echo "$file" | tee -a ./"file-list.txt"\ndone\n
Run Code Online (Sandbox Code Playgroud)\n
\n

将循环的输出传送到另一个命令

\n

此外,我们可以将循环的输出通过管道或重定向到另一个命令或函数:

\n
while IFS= read -r -d \'\' item; do\n    # Compose the name of the new file\n    DIR="$(dirname "${item}")"\n    FILE_NAME="$(basename "${item}")"\n    NEW_FILE_NAME="new-${FILE_NAME}"\n\n    # move the file and suppress the potential output \n    # of the \'mv\' command by redirecting it to a log file \n    mv "${item}" "${DIR}/${NEW_FILE_NAME}" >>/tmp/mv-loop.log 2>&1\n\n    # output the name of the new file in order to be processed \n    # by the next (piped) command\n    printf \'%b\' "${DIR}/${NEW_FILE_NAME}"\'\\0\'\ndone < <(find . -type f -print0) | xargs -0 -I{} 7z a -t7z "the_archive_name.7z" {}\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,在上面的示例中,到处都使用了空分隔符:

\n
    \n
  • find . -print0,
  • \n
  • IFS= read -r -d \'\' item-参考
  • \n
  • printf \'%b\' a\'\\0\'b-参考
  • \n
  • xargs -0(在这种情况下,我们实际上不需要-I{}and{}命令xargs)。
  • \n
\n

此示例将递归地移动(重命名)所有文件,但在存档中不会出现目录结构。

\n


pLu*_*umo 1

有没有一种简单又通用的方法可以做到

答:不,每个命令都不同。


关于您的问题:

  1. 您不需要-t,但随后mv将为每个文件运行,这会慢很多。你需要以而不是结束你-exec的。\;+

  2. 管道与循环无关for,管道将标准输出从管道左侧发送到右侧的标准输入。从标准输入(或带有选项的文件)xargs读取并使用从输入中获取的参数运行命令。-a

  3. ls没有-exec选择。ls 可以与 一起使用xargs,但不能与 一起使用xargs -0,因为ls没有 NULL 分隔输出的选项。这也是为什么你根本不应该使用ls管道(文件名允许有换行符)。

  4. 对于mv-t目标目录,而对于7z它是存档类型,你为什么认为它应该起作用?

对我来说,您似乎正在使用您并不真正理解的命令。这不适用于任何编程或脚本语言。


顺便说一句:您应该使用xargswith-r选项来避免空输入的问题。