【问题标题】:Handle special characters in bash for...in loop在 bash for...in 循环中处理特殊字符
【发布时间】:2009-10-14 01:44:33
【问题描述】:

假设我有一个文件列表

file1
"file 1"
file2

for...in 循环在空格之间分解,而不是换行符:

for x in $( ls ); do
   echo $x
done

结果:

file
1
file1
file2

我想对每个文件执行一个命令。上面的“文件”和“1”不是实际文件。如果文件名包含空格或逗号等内容,我该怎么做?

这比我想象的要复杂一些 find -print0 | xargs -0 可以处理,因为我实际上希望命令类似于“convert input/file1.jpg .... output/file1.jpg”,所以我需要在此过程中置换文件名。

【问题讨论】:

    标签: bash command-line shell


    【解决方案1】:

    实际上,Mark 的建议可以很好地工作,甚至无需对内部字段分隔符做任何事情。问题是在子 shell 中运行 ls ,无论是通过反引号还是 $( ) 都会导致 for 循环无法区分名称中的空格。只需使用

    for f in *
    

    而不是 ls 解决了问题。

    #!/bin/bash
    for f in *
    do
     echo "$f"
    done
    

    【讨论】:

    • 乔丹,我没有看到 eduffy 的解决方案有任何问题。我尝试使用其中包含空格的文件。实际上, ls -1 不会创建子 shell。它只是创建了另一个进程,仅此而已。
    • 我同意,它对我来说很好用。老实说,考虑到当我发表此评论时,以及我从“Mark”中提到的答案缺失的事实,我认为已经丢失了一些可能更有意义的上下文。 @eduffy 的解决方案很好,额外的过程并不是什么大问题,但如果在非常大的一组位置上实现自动化,/也许/它会稍微慢一些,但我怀疑这在现实世界中是否会成为问题。
    【解决方案2】:

    UPDATE BY OP:这个答案很烂,不应该放在首位……@Jordan 下面的帖子应该是公认的答案。

    一种可能的方式:

    ls -1 | while read x; do
       echo $x
    done
    

    【讨论】:

    • @ʞɔıu,如果答案有误,您可以不接受,以免误导任何人。
    • @codeforester - 我做了编辑说答案很糟糕,而不是ʞɔıu。
    【解决方案3】:

    我知道这个问题已经很久没有“回答”了,尽管对 eduffy 表示尊重,但我想出了一个更好的方法,我想我会分享它。

    eduffy 的答案的“错误”不是它是错误的,而是它强加了对我来说是一个痛苦的限制:当 ls 的输出通过管道传输时,隐含创建了一个子shell,这意味着变量集循环退出后,循环内部会丢失。因此,如果你想写一些更复杂的代码,你会感到很痛苦。

    我的解决方案是使用“readline”函数并从中编写一个程序,您可以在其中指定任何特定的行号,您可能希望从任何给定的函数调用中得到结果。 ... 举个简单的例子,从 eduffy 开始:

    ls_output=$(ls -1)
    # The cut at the end of the following line removes any trailing new line character
    declare -i line_count=$(echo "$ls_output" | wc -l | cut -d ' ' -f 1)
    declare -i cur_line=1 
    while [ $cur_line -le $line_count ] ;
    do  
       # NONE of the values in the variables inside this do loop are trapped here.
       filename=$(echo "$ls_output" | readline -n $cur_line)
       # Now line contains a filename from the preceeding ls command
       cur_line=cur_line+1
    done
    

    现在您已将所有子shell 活动封装到整洁的小包中,并且可以进行shell 编码,而不必担心变量值的范围会被困在子shell 中。

    如果有人想要副本,我在 gnuc 中编写了我的 readline 版本,在这里发布有点大,但也许我们可以找到一种方法......

    希望这会有所帮助, 反转录

    【讨论】:

      猜你喜欢
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 2017-12-29
      • 2018-05-07
      • 2014-09-13
      相关资源
      最近更新 更多