【问题标题】:how to output file names surrounded with quotes in SINGLE line?如何在单行中输出用引号括起来的文件名?
【发布时间】:2011-08-27 20:22:27
【问题描述】:

我想按以下方式输出文件夹中的项目列表:

"filename1"  "filename2" "file name with spaces" "foldername" "folder name with spaces"

换句话说,项目名称必须在一行中,用引号(单引号或双引号)括起来并用空格分隔。

我知道

find . | xargs echo

在一行中打印输出,但我不知道如何在每个项目名称周围添加引号。

此代码是 bsh 脚本的一部分。 因此,解决方案可以是一组命令并使用临时文件来存储中间输出。

非常感谢您的任何建议。

干杯,安娜

【问题讨论】:

  • 如果目标是将带有空格的名称传递给 xargs,那么文字引号是错误的做法。

标签: bash unix find xargs


【解决方案1】:

您也可以简单地使用 find "-printf",如:

find . -printf "\"%p\" " | xargs your_command

地点:

%p = file-path

这将用引号括住每个找到的文件路径,并用空格分隔每个项目。 这样可以避免使用多个命令。

【讨论】:

  • 这应该被标记为正确答案。正则表达式操作太低级了。
  • 我必须在 Windows 上使用 cygwin 添加一个新行以使输出相同:-printf "\"%p\" \n"
  • -printf 在 OSX 上不可用。
  • @Nimrod 与 Homebrew:brew install findutils --with-default-names
  • ...如果文件名包含引号,则会失败。
【解决方案2】:

这应该可以工作

find $PWD | sed 's/^/"/g' | sed 's/$/"/g' | tr '\n' ' '

编辑:

这应该比上一个效率更高。

find $PWD | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '

@Timofey 的解决方案最终可以使用 tr,并且应该是最有效的。

find $PWD -exec echo -n '"{}" ' \; | tr '\n' ' '

【讨论】:

  • 这很好用!非常感谢。我的最终命令现在是:“find . ! -type l ( -name . -o -prune ) | sort -n | sed 's/^/"/g' | sed 's/$/"/g' | tr '\n' ' ' | xargs myCommand"。需要这一行作为 myCommand 的输入参数。
  • 请,请不要。首先,如果您的 $PWD 包含扩展为任何内容的空格或文字 glob 字符,find $PWD 将表现不佳。其次,将双引号替换为名称以试图转义它是一种弱且容易被规避的机制——有效的文件名本身可以包含"' 字符,因此会丢弃整个流其余部分的解析。跨度>
  • @Ana,如果在带有 GNU 工具(find -print0sort -z)的系统上,最好使用 find ... -print0 | sort -n -z | xargs -0 myCommand
  • @Ana, ...即使您不想使用 NUL 定界符,您仍然可以告诉 xargs 仅使用换行符定界符,并且对带有空格的文件名是安全的(尽管不是带有空格的文件名)换行符,但您已经接受的答案对于包含换行符的文件名也已经不安全):find ... | sort -n | xargs -d $'\n' myCommand
  • 你真的应该使用“ls”来列出目录内容。它确实有所需的选项。
【解决方案3】:

您可以使用 GNU ls 选项 --quoting-style 轻松获得您想要的东西。从手册页:

--quoting-style=WORD

对条目名称使用引用样式WORDliterallocaleshellshell-alwaysshell-escapeshell-escape-alwayscescape

例如,使用命令ls --quoting-style=shell-escape-always,您的输出变为:

'filename1' 'filename2' 'file name with spaces' 'foldername' 'folder name with spaces'

使用--quoting-style=c,您可以准确地重现您想要的示例。但是,如果要由 shell 脚本使用输出,则应使用能够正确转义特殊字符的格式之一,例如 shell-escape-always

【讨论】:

  • related: 'ls -Q' ;# 加双引号
  • 我建议:ls -1 --quoting-style=c --> "file one" "file two" etc.。谢谢。
【解决方案4】:

试试这个。

find . -exec echo -n '"{}" ' \;

【讨论】:

  • 去掉 -n 得到包含换行符的结果。
  • 在 Solaris 11 上不起作用,只能打印很多次 -n "{}"
【解决方案5】:
for f in *; do printf "'%s' " "$f"; done; echo

或者,感谢Gordon Davisson

printf "'%s' " *; echo

结尾的echo 只是在输出中添加换行符。

【讨论】:

  • 这可以进一步简化:printf "'%s' " *.
【解决方案6】:

10 年后,没有人提出 Bash “|while read” 方法?

find * -type d -depth 0|while read f; do echo \"$f\"; done

这是一个简单的 Bash shell 管道,而不是启动另一个程序,如 sed 或 xarg。如果你真的想对每个文件/文件夹做点什么:

find * -type d -depth 0|while read f; do du -sh "$f"; done

顺便说一句,find * 使用了另一个 Bash 功能,它排除了 .xyz 文件/文件夹,并且不会输出 ./ 前缀 find .

【讨论】:

    【解决方案7】:

    编辑:
    以下答案生成 换行符分隔的 LIST 而不是单行。

    1. 我第二次猜测 OP 使用结果来调用其他命令
    2. 将输出 LIST 转换为单行很容易 (| tr '\n' ' ')

    一个较少提及的方法是使用xargs-d (--delimiter) 选项:

    find . | xargs -I@ -d"\n" echo \"@\" 
    

    -I@ 将每个find 结果捕获为@,然后我们用引号对其进行回显

    使用它,您可以调用任何命令,就像在参数中添加引号一样。

    $ find . | xargs -d"\n" testcli.js
    [ "filename1",
      "filename2",
      "file name with spaces",
      "foldername",
      "folder name with spaces" ]
    

    https://stackoverflow.com/a/33528111/665507

    【讨论】:

      【解决方案8】:

      试试

      ls | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '
      

      【讨论】:

        【解决方案9】:
            find . | sed "s|.*|\"&\"|"
        

        简要说明:
        我们将 .* 模式的结果放在引号中。
        好的来源是sed

        详细说明:
        模式:s/one/ONE/

        • s 替换命令。
        • / 分隔符。
          在我的表达式中,使用 "|" 代替 "/" 来防止像模式 s/ 中的“山” .*/\"&\"/.
        • 一个正则表达式模式搜索模式。
        • ONE 替换字符串。
        • .* 表示任何重复无限次的符号。
        • \" 表示 " 本身。
        • & 与找到的模式相对应的特殊字符。

        【讨论】:

        • 请解释你的答案。
        【解决方案10】:

        为避免黑客尝试手动添加引号,您可以利用 printfs %q 格式化选项:

        ❯ ll .zshrc.d
        total 112K
        -rwxrwxrwx 1 root root  378 Jul  1 04:39  options.zsh*
        -rwxrwxrwx 1 root root   57 Jul  1 04:39  history.zsh*
        -rwxrwxrwx 1 root root  301 Jul  1 05:01  zinit.zsh*
        -rwxrwxrwx 1 root root  79K Jul  1 05:19  p10k.zsh*
        -rwxrwxrwx 1 root root  345 Jul  1 05:24  zplugins.zsh*
        -rwxrwxrwx 1 root root  490 Jul  4 23:40  aliases.zsh*
        -rw-r--r-- 1 root root 9.0K Jul 27 08:14  lscolors.zsh
        -rw-r--r-- 1 root root    0 Aug 30 05:56 'foo bar'
        -rw-r--r-- 1 root root    0 Aug 30 05:58 '"foo"'
        
        ❯ find .zshrc.d -exec printf '%q ' {} +
        .zshrc.d .zshrc.d/history.zsh .zshrc.d/aliases.zsh .zshrc.d/zplugins.zsh .zshrc.d/p10k.zsh .zshrc.d/zinit.zsh .zshrc.d/options.zsh '.zshrc.d/"foo"' '.zshrc.d/foo bar' .zshrc.d/lscolors.zsh #
        

        对比:

        find .zshrc.d -printf "\"%p\" "
        ".zshrc.d" ".zshrc.d/history.zsh" ".zshrc.d/aliases.zsh" ".zshrc.d/zplugins.zsh" ".zshrc.d/p10k.zsh" ".zshrc.d/zinit.zsh" ".zshrc.d/options.zsh" ".zshrc.d/"foo"" ".zshrc.d/foo bar" ".zshrc.d/lscolors.zsh" #
        

        请注意文件.zshrc.d/"foo" 被错误地转义。

        ❯ echo ".zshrc.d/"foo""
        .zshrc.d/foo
        
        ❯ echo '.zshrc.d/"foo"'
        .zshrc.d/"foo"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-02
          • 2012-12-21
          • 1970-01-01
          • 2011-09-27
          • 1970-01-01
          • 2010-12-09
          • 2015-11-14
          • 2010-10-18
          相关资源
          最近更新 更多