`ls` 在 bash 脚本内部和外部的行为不同

jdo*_*066 4 bash shell-script synology

我正在使用 Synology NAS。我有一个要删除的文件列表,在名为Myfiles.txt.\xc2\xa0\n的文件中列出了完整路径。\xc2\xa0 文件有大约 3000\xc2\xa0 行,如下所示:

\n
"/volume2/NBU/Downloads/AA_To be seen/Life.Itself.2018.1080p.WEB-DL.DD5.1.H264-FGT/RARBG.txt"\n"/volume2/nbU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E16.High.Stakes.Hip.Hop.WEBRip.x264-ION10.mp4"\n"/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4"\n
Run Code Online (Sandbox Code Playgroud)\n

我正在使用以下脚本\n(测试 并ls稍后替换为rm\xc2\xa0-f):

\n
#!/bin/bash\nwhile IFS="" read -r p;\ndo\n  ls "$p"\ndone < "Myfiles.txt"\n
Run Code Online (Sandbox Code Playgroud)\n

不幸的是,当我执行脚本时,每个循环都会出错并显示以下消息:

\n
ls: cannot access "/volume2/NBU/Downloads/AA_To be seen/Life.Itself.2018.1080p.WEB-DL.DD5.1.H264-FGT/RARBG.txt": No such file or directory\nls: cannot access "/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E16.High.Stakes.Hip.Hop.WEBRip.x264-ION10.mp4": No such file or directory\nls: cannot access "/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4": No such file or directory\n
Run Code Online (Sandbox Code Playgroud)\n

但是当我直接从命令行执行该行时,它就可以工作。\xc2\xa0\nFor\xc2\xa0example:

\n
ll "/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4"\n
Run Code Online (Sandbox Code Playgroud)\n

给出输出:

\n
-rwxrwxrwx+ 1 Pansysadmin users 275337817 Dec 15  2018 /volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4\n
Run Code Online (Sandbox Code Playgroud)\n

即使当我使用 执行脚本时sudo,它也会给出相同的错误。

\n

我在忽略什么?

\n

roa*_*ima 9

引号不是文件名的一部分。您正在尝试删除诸如 之类的文件,"file.txt"但该文件实际上名为file.txt.

touch "file.txt"    # shell uses quotes; name is simply file.txt
ls "file.txt"       # quotes used by shell; success
ls file.txt         # no quotes; success
ls '"file.txt"'     # outer quotes used by shell to treat word-with-quotes as literal; failure
Run Code Online (Sandbox Code Playgroud)

修复名称文件,使文件名正确(即文件名周围没有双引号),或者修改循环以删除数据的不正确部分。

我刚刚看到你关于尝试的评论sudosudo在未首先了解您可能需要它的原因之前,请不要求助于它。(在这里,你不需要。)否则有一天,你可能最终会破坏你的系统,因为你无意中绕过了它试图为你提供的保护。


G-M*_*ca' 7

为了扩大roaima\xe2\x80\x99s 的答案

\n
    \n
  • 当您向 shell 发出命令时,\nit 在\xc2\xa0 命令行上进行大量处理和解释。\xc2\xa0\n例如:

    \n\n
  • \n
  • 当该read命令读取输入时,它不会执行任何处理。\xc2\xa0\n特别是,如果您的read\xc2\xa0input\n 行包含*>和 等特殊字符",\nit 只是将这些字符放入p变量中。\ xc2\xa0\n空格和制表符通常仍然有一些特殊含义,\n但是你\xe2\x80\x99成功地用 抑制了它IFS=。\xc2\xa0\n反斜杠 ( \\) 通常仍然有一些特殊含义,\n但是你\xe2\x80 \x99re 成功地用read\xc2\xa0-r.\xc2\xa0\n 抑制了这一点,因此 \xc2\xa0p被设置为 \xc2\xa0"开头和结尾的文件名。

    \n
  • \n
  • 扩展变量的值\是 shell 执行的最后一件事之一。\xc2\xa0\n因此,例如,您可以执行类似的操作

    \n
    statement="Math tells us that 5 > 4."\necho $statement\n
    Run Code Online (Sandbox Code Playgroud)\n

    并且 shell 将写入Math tells us that 5 > 4.(到 \xc2\xa0the\xc2\xa0 终端),\n因为它\n不检查 \xc2\xa0 变量的内容statement\n为 \xc2\xa0 \ >xc2\xa0 字符。

    \n

    注意:上面是一个不好的例子。\xc2\xa0\n一般来说你应该说

    \n
    echo "$statement"\n
    Run Code Online (Sandbox Code Playgroud)\n

    即,带引号。

    \n
  • \n
  • 所以,当你说

    \n
    ls "$p"\n
    Run Code Online (Sandbox Code Playgroud)\n

    shellls使用包含引号字符的参数运行。\xc2\xa0\n它\xe2\x80\x99s 本质上与\xc2\xa0saying 相同

    \n
    ls \'"/volume2/NBU/Downloads/AA_To be seen/Life.Itself \xe2\x80\xa6 H264-FGT/RARBG.txt"\'\n
    Run Code Online (Sandbox Code Playgroud)\n

    (注意引号内的引号)。\xc2\xa0\n并且实际文件的名称不包含\xe2\x80\x99t 包含引号字符。

    \n
  • \n
\n