Bash 如何在单行中输出带引号的文件名?

Bash 如何在单行中输出带引号的文件名?,bash,unix,find,xargs,Bash,Unix,Find,Xargs,我想按以下方式输出文件夹中的项目列表: "filename1" "filename2" "file name with spaces" "foldername" "folder name with spaces" 换句话说,项目名称必须在一行中,用引号(单引号或双引号)包围,并用空格分隔 我知道 find . | xargs echo 在一行中打印输出,但我不知道如何在每个项目名称周围添加引号 此代码是bsh脚本的一部分。 因此,解决方案可以是一组命令,并使用临时文件来存储中间输出 非常感

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

"filename1"  "filename2" "file name with spaces" "foldername" "folder name with spaces"
换句话说,项目名称必须在一行中,用引号(单引号或双引号)包围,并用空格分隔

我知道

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

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

非常感谢你的建议

干杯,安娜试试这个

find . -exec echo -n '"{}" ' \;
这应该行得通

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

这应该比前一个更有效

find $PWD | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '
@蒂莫菲的解决方案最终将与tr一起使用,并且应该是最有效的

find $PWD -exec echo -n '"{}" ' \; | tr '\n' ' '
或者,多亏了:


尾随的
echo
只是向输出添加一个换行符。

您也可以简单地使用find“-printf”,如下所示:

其中:

%p = file-path
这将用引号围绕找到的每个文件路径,并用空格分隔每个项目。 这避免了使用多个命令。

编辑:
下面的答案生成一个新的行分隔列表,而不是一行

  • 我猜测OP会使用结果调用其他命令
  • 将输出列表转换为单行很容易(
    |tr'\n'

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

    find . | xargs -I@ -d"\n" echo \"@\" 
    
    -I@
    将每个
    查找
    结果捕获为
    @
    ,然后用引号将其回显

    这样,您就可以在为参数添加引号时调用任何命令

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

    请参见

    您可以使用GNU
    ls
    选项
    --quoting style
    轻松获取所需内容。从手册页面:

    --quoting style=WORD

    对条目名称使用引用样式
    WORD
    literal
    locale
    shell
    shell始终
    shell转义始终
    c
    escape

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

    'filename1' 'filename2' 'file name with spaces' 'foldername' 'folder name with spaces'
    
    使用
    --quoting style=c
    ,您可以准确地重现所需的示例。但是,如果输出将由shell脚本使用,则应使用正确转义特殊字符的表单之一,例如
    shell转义始终

    try

    ls | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '
    
    简要说明:
    我们将。*模式的结果放入引号中。
    好的来源是。

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

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

    为了避免黑客试图手动添加引号,您可以利用
    printf
    s
    %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 #
    
    vs:

    请注意,文件
    .zshrc.d/“foo”
    的转义错误

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

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

    这是一个简单的bashshell管道,而不是启动另一个程序,如sed或xarg。如果确实要对每个文件/文件夹执行某些操作:

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

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

    这非常有效!非常感谢你。现在,我的最后一个命令是:“find.!-typel(-name.-o-prune)| sort-n | sed's/^/“/g'| sed's/$/”/g'| tr'\n''| xargs myCommand”。这一行是myCommand的输入参数。请,请不要。首先,
    find$PWD
    如果您的
    $PWD
    包含空格或文本全局字符,并且这些字符可以扩展为任何内容,那么它将表现得很差。其次,用双引号替换名称以试图转义它是一种脆弱且容易规避的机制——有效的文件名本身可以包含
    字符,从而中断对整个流其余部分的解析。@Ana,如果在使用GNU工具的系统上(
    find-print0
    sort-z
    ),最好使用
    find…-print0 | sort-n-z | xargs-0 myCommand
    @Ana,…即使您不想使用NUL分隔符,您仍然可以告诉
    xargs
    仅使用换行分隔符,并对带有空格的文件名保持安全(虽然不是带换行符的文件名,但您已经接受的答案对于包含换行符的文件名也已经不安全):
    find…| sort-n | xargs-d$'\n'myCommand
    您确实应该使用“ls”来列出目录内容。它确实有必要的选项。这可以进一步简化:
    printf''%s'*
    .remove-n以获得包含换行符的结果。在Solaris 11上不起作用,只打印
    -n“{}”
    很多次!如果目标是将带空格的名称传递给xargs,则使用文字引号是错误的方式。这应该标记为正确答案。regex操作级别太低。我必须在Windows上使用cygwin添加新行,以使输出相同:
    -printf“\%p\”\n
    -printf在OSX上不可用。@Nimrod With Homebrew:
    brew安装findutils--使用默认名称
    …如果文件名包含引号,则会显著失败。相关:“ls-Q”#添加双引号我建议:
    ls-1--quoting style=c    find . | sed "s|.*|\"&\"|"
    
    ❯ 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" #
    
    ❯ echo ".zshrc.d/"foo""
    .zshrc.d/foo
    
    ❯ echo '.zshrc.d/"foo"'
    .zshrc.d/"foo"
    
    find * -type d -depth 0|while read f; do echo \"$f\"; done
    
    find * -type d -depth 0|while read f; do du -sh "$f"; done