Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell 为什么不';“我需要通过考试”\&引用;{}\"&引用;在处理带有空格的文件名时是否要使用xargs?_Shell_Find_Xargs - Fatal编程技术网

Shell 为什么不';“我需要通过考试”\&引用;{}\"&引用;在处理带有空格的文件名时是否要使用xargs?

Shell 为什么不';“我需要通过考试”\&引用;{}\"&引用;在处理带有空格的文件名时是否要使用xargs?,shell,find,xargs,Shell,Find,Xargs,我有以下问题: 我想使用xargs find结构来查找文件。 不同之处在于,我不想在中使用find作为command1,而是作为command2使用: command1 | xargs command2 如果文件名中有空格,则会出现问题 例如: 如果我正在尝试: echo 01.Here Comes The Night Time II.flac | xargs -pi find ~/Multimedia/Musik/flac/ -name "\""{}"\"" find ~/Multimed

我有以下问题:

我想使用xargs find结构来查找文件。 不同之处在于,我不想在中使用find作为command1,而是作为command2使用:

command1 | xargs command2
如果文件名中有空格,则会出现问题

例如:

如果我正在尝试:

echo 01.Here Comes The Night Time II.flac | xargs -pi find ~/Multimedia/Musik/flac/ -name "\""{}"\""

find ~/Multimedia/Musik/flac/ -name "01.Here Comes The Night Time II.flac" ?...yes
什么也找不到。 此外,对于xargs的-0选项,它也不起作用

如果复制并粘贴来自xargs的交互式打印请求,将找到该文件:

find ~/Multimedia/Musik/flac/ -name "01.Here Comes The Night Time II.flac"

~/Multimedia/Musik/flac/Arcade Fire/Reflektor (CD 2)/01.Here Comes The Night Time II.flac

我“输入”管道的方式,或者在find命令中包含“输入”的方式(我通过尝试和错误解决了这个问题)或者其他方面是否有问题?

您似乎对程序内部启动的方式以及shell如何解释命令感到困惑

在unix中,启动程序涉及三个参数:

  • 文件名。这是一个字符串,包含要运行的程序的路径
  • 字符串列表。按照惯例,我们称这些为“命令行参数”
  • 另一个字符串列表。按照惯例,我们称之为“环境”,但在操作系统级别,它只是另一个字符串列表。然而,所有程序/库合谋对用户和应用程序程序员隐藏这一点
  • 在shell中键入命令时,会发生很多事情,但在最简单的情况下,它只是一堆空格分隔的单词:

    $ foo bar baz
    
    $
    表示shell提示符,而不是您键入的内容。)

    shell将此行拆分为三个单词(
    foo
    bar
    baz
    ),并将第一个单词解释为程序名(在
    路径
    变量中列出的目录中查找).让我们假设
    PATH
    列出了
    /usr/bin
    ,并且确实存在一个
    /usr/bin/foo
    程序

    现在,shell按如下方式启动程序(伪代码):

    也就是说,我们在
    /usr/bin/foo
    中运行可执行文件,将三个字符串的列表作为参数传递。 (
    […]
    表示环境,从现在起我们将忽略它。)

    如果你这样做会发生什么

    $ foo "bar baz"
    
    引号会影响shell将行拆分为单词的方式。特别是引号中的“
    (空格)不起分隔符的作用,而是按字面意思。这给了我们一个两元素列表(
    foo
    bar baz
    )。请注意,引号不是单词本身的一部分

    在内部,这将转换为以下调用:

    exec("/usr/bin/foo", ["foo", "bar baz"], [...])
    
    exec("/usr/bin/xargs", ["xargs", "-pi", "find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "\"{}\""], [...])
    
    同样,第二个参数只包含一个空格,没有嵌入引号

    那么像这样的命令会发生什么呢

    $ xargs -pi find ~/Multimedia/Musik/flac/ -name "\""{}"\""
    
    ?

    shell将再次将其解析为单词列表。
    ~
    将替换为主目录的名称。
    “\”
    只是一种复杂的书写方式。
    \“
    (即文字
    字符)。我们最后得到的列表是
    xargs
    -pi
    find
    /home/madZeo/Multimedia/Musik/flac/
    -name
    “{}”
    。这转化为以下调用:

    exec("/usr/bin/foo", ["foo", "bar baz"], [...])
    
    exec("/usr/bin/xargs", ["xargs", "-pi", "find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "\"{}\""], [...])
    
    请注意,最后一个参数是4个字符的字符串
    “{}”

    xargs
    将其第一个参数(
    -pi
    )视为选项规范。特别是,
    -i
    告诉它用从标准输入读取的当前值替换参数列表中的
    {}

    xargs
    然后从其标准输入读取一行,这(因为您的
    echo
    管道)给出
    01。这里是夜间II.flac

    它被替换为
    {}
    ,生成列表
    find
    /home/madZeo/Multimedia/Musik/flac/
    -name
    “01.这里是夜间II.flac”
    xargs
    ,然后调用
    find
    ,如下:

    exec("/usr/bin/find", ["find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "\"01.Here Comes The Night Time II.flac\""], [...])
    
    $ xargs -pi find ~/Multimedia/Musik/flac/ -name {}
    
    这告诉
    find
    查找一个文件,其名称以
    (引号字符)开头。不存在这样的文件,因此此操作失败


    修复方法是编写如下命令:

    exec("/usr/bin/find", ["find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "\"01.Here Comes The Night Time II.flac\""], [...])
    
    $ xargs -pi find ~/Multimedia/Musik/flac/ -name {}
    
    这最终会运行起来

    exec("/usr/bin/find", ["find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "01.Here Comes The Night Time II.flac"], [...])
    
    ,这就是你想要的

    问题在于
    xargs
    直接运行其子命令(
    find
    )。它不会构造一个新的命令行,该命令行会被shell重新解析。它不在空格上拆分传入参数,不解释引号,不关心像
    $
    *
    \
    这样的“特殊”字符。它只是获取给定的单词列表,用当前输入替换子字符串
    {}
    的任何出现,然后执行它


    如果您天真地接受最后一个命令并将其粘贴到shell中,它将经历分词、删除引号等过程,从而导致不同的结果。

    您似乎对程序内部启动的方式以及shell如何解释命令感到困惑

    在unix中,启动程序涉及三个参数:

  • 文件名。这是一个字符串,包含要运行的程序的路径
  • 字符串列表。按照惯例,我们称这些为“命令行参数”
  • 另一个字符串列表。按照惯例,我们称之为“环境”,但在操作系统级别,它只是另一个字符串列表。然而,所有的程序/库合谋使用户和应用程序程序员都不知道这一点
  • 在shell中键入命令时,会发生很多事情,但在最简单的情况下,它只是一堆空格分隔的单词:

    $ foo bar baz
    
    $
    表示shell提示符,而不是您键入的内容。)

    shell将此行拆分为三个单词(
    foo
    bar
    baz
    ),并将第一个单词解释为程序名(在
    路径
    变量中列出的目录中查找)。让我们像