【问题标题】:How to get the list of files in a directory in a shell script?如何在shell脚本中获取目录中的文件列表?
【发布时间】:2011-01-27 02:30:13
【问题描述】:

我正在尝试使用 shell 脚本获取目录的内容。

我的脚本是:

for entry in `ls $search_dir`; do
    echo $entry
done

其中$search_dir 是相对路径。但是,$search_dir 包含许多名称中带有空格的文件。在这种情况下,此脚本不会按预期运行。

我知道我可以使用for entry in *,但这仅适用于我当前的目录。

我知道我可以切换到那个目录,使用 for entry in * 然后再改回来,但我的特殊情况阻止了我这样做。

我有两个相对路径 $search_dir$work_dir,我必须同时处理这两个路径,读取它们在其中创建/删除文件等。

那我现在该怎么办?

PS:我使用 bash。

【问题讨论】:

    标签: bash shell directory-listing


    【解决方案1】:
    search_dir=/the/path/to/base/dir/
    for entry in "$search_dir"/*
    do
      echo "$entry"
    done
    

    【讨论】:

    • 你能解释一下为什么for entry in "$search_dir/*" 不起作用吗?为什么我们需要将/* 放在引号之外?
    • @mrgloom:因为你需要让 shell glob 通配符。
    • 解决方案给出了完整路径。如果我只想列出当前目录中的内容怎么办?
    • @mrgloom 如果你想这样做,你可以使用for entry in "${search_dir}/*"
    • @Anish B:停止破坏原始帖子。答案是正确的,因为它是写的
    【解决方案2】:

    ls $search_path ./* |grep ".txt"| 而 IFS= 读取 -r 行 做 无论“$line” 完成

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案3】:
    $ pwd; ls -l
    /home/victoria/test
    total 12
    -rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  a
    -rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  b
    -rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  c
    -rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'c d'
    -rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  d
    drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_a
    drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_b
    -rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'e; f'
    
    $ find . -type f
    ./c
    ./b
    ./a
    ./d
    ./c d
    ./e; f
    
    $ find . -type f | sed 's/^\.\///g' | sort
    a
    b
    c
    c d
    d
    e; f
    
    $ find . -type f | sed 's/^\.\///g' | sort > tmp
    
    $ cat tmp
    a
    b
    c
    c d
    d
    e; f
    

    变体

    $ pwd
    /home/victoria
    
    $ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
    /home/victoria/new
    /home/victoria/new1
    /home/victoria/new2
    /home/victoria/new3
    /home/victoria/new3.md
    /home/victoria/new.md
    /home/victoria/package.json
    /home/victoria/Untitled Document 1
    /home/victoria/Untitled Document 2
    
    $ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
    new
    new1
    new2
    new3
    new3.md
    new.md
    package.json
    Untitled Document 1
    Untitled Document 2
    

    注意事项:

    • .:当前文件夹
    • 移除 -maxdepth 1 以递归搜索
    • -type f :查找文件,而不是目录 (d)
    • -not -path '*/\.*':不返回.hidden_files
    • sed 's/^\.\///g' :从结果列表中删除前面的 ./

    【讨论】:

      【解决方案4】:

      接受的答案不会返回带有 . 为此,请使用

      for entry in "$search_dir"/* "$search_dir"/.[!.]* "$search_dir"/..?*
      do
        echo "$entry"
      done
      

      【讨论】:

        【解决方案5】:

        这是在目录中列出文件的另一种方式(使用不同的工具,不如其他一些答案高效)。

        cd "search_dir"
        for [ z in `echo *` ]; do
            echo "$z"
        done
        

        echo * 输出当前目录下的所有文件。 for 循环遍历每个文件名并打印到标准输出。

        此外,如果在目录中查找目录,请将其放在 for 循环中:

        if [ test -d $z ]; then
            echo "$z is a directory"
        fi
        

        test -d 检查文件是否为目录。

        【讨论】:

        • for [ z 是语法错误。 if [ test 是愚蠢和错误的。不引用 "$z" 是引用错误。
        • 请解释一下。当我写下答案时,我成功地运行了代码。如果您要进行 necropost 至少是有用的。
        • 要解释什么?如果您当时对此进行了测试,那么您肯定没有使用标准外壳。我已经指出了错误,甚至从这里的其他一些答案中查找正确的语法应该不难。但是看看这个演示:ideone.com/ERcu2c 并按你的心意来分叉。
        • 如果您认为这无关紧要,因为它已经过时了,那么您就不了解 Stack Overflow 是如何工作的。对于发布此常见问题的重复内容的新用户来说,这经常 - 可能每天 - 链接为规范答案,但也可能从 Google 搜索中获得 100 倍的流量。
        【解决方案6】:

        这是一种让我更容易理解语法的方法:

        yourfilenames=`ls ./*.txt`
        for eachfile in $yourfilenames
        do
           echo $eachfile
        done
        

        ./ 是当前工作目录,但可以替换为任何路径
        *.txt 返回anything.txt
        您可以通过直接在终端中输入ls 命令来轻松查看将列出的内容。

        基本上,您创建一个变量yourfilenames,其中包含列表命令作为单独元素返回的所有内容,然后循环遍历它。该循环创建了一个临时变量eachfile,其中包含它正在循环的变量的单个元素,在本例中为文件名。这不一定比其他答案更好,但我觉得它很直观,因为我已经熟悉 ls 命令和 for 循环语法。

        【讨论】:

        • 这适用于快速、非正式的脚本或单行脚本,但如果文件名包含换行符,它将中断,这与基于 glob 的解决方案不同。
        • @SorenBjornstad 感谢您的建议!我不知道文件名中允许换行 - 什么样的文件可能有它们?比如,这是经常发生的事情吗?
        • 由于这个原因,文件名中的换行符是邪恶的,据我所知,没有正当理由使用它们。我自己从未在野外见过一只。也就是说,完全有可能通过换行符恶意构造文件名以利用这一点。 (例如,想象一个包含文件ABC 的目录。您创建名为B\nCD 的文件,然后选择删除它们。不处理此权限的软件可能会结束即使您没有这样做的权限,也要删除先前存在的文件 B 和 C。)
        • mywiki.wooledge.org/ParsingLs 解释了这种方法的大量缺陷。您基本上不应该在脚本中使用ls。无论如何,这很愚蠢;在 ls 运行时,shell 已经扩展了通配符。
        【解决方案7】:
        find "${search_dir}" "${work_dir}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 -I {} echo "{}"
        

        【讨论】:

        • 我知道这已经很老了,但我似乎无法获得最后一个 xargs -0 -i echo "{}" 命令,愿意解释一下吗?特别是-i echo "{}" 部分是做什么的?我还从man 页面读到-i 现在已弃用,我们应该使用-I insted。
        • -i 用 arg 替换 {}
        • 谢谢!这很有用,对于像我这样思想迟钝的人来说,我认为{} 是由find 命令替换为匹配项的字符串。
        • 你为什么使用xargs?默认情况下,find 打印它找到的内容...您可以删除 -print0 中的所有内容。
        • 这样做不能很好地处理带有空格的文件条目。
        【解决方案8】:

        这里的其他答案很好,可以回答你的问题,但这是“bash 获取目录中文件列表”的最高谷歌结果,(我正在寻找保存文件列表)所以我想我将发布该问题的答案:

        ls $search_path > filename.txt
        

        如果您只想要某种类型(例如任何 .txt 文件):

        ls $search_path | grep *.txt > filename.txt
        

        注意 $search_path 是可选的; ls > filename.txt 会做当前目录。

        【讨论】:

        • 无需使用 grep 仅获取 .txt 文件:`ls $search_path/*.txt > filename.txt'。但更重要的是,不应该使用 ls 命令的输出来解析文件名。
        • @VictorZamanian,你能详细说明为什么我们不应该使用ls 的输出来解析文件名吗?以前没听说过。
        • @samurai_jane 关于这个主题有很多链接可以提供,但这是第一个搜索结果:mywiki.wooledge.org/ParsingLs。我什至在这里看到一个关于 SO 的问题,声称不解析 ls 输出的原因是 BS 并且对此非常详尽。但是答复/答案仍然声称这是一个坏主意。看看:unix.stackexchange.com/questions/128985/…
        【解决方案9】:
        for entry in "$search_dir"/* "$work_dir"/*
        do
          if [ -f "$entry" ];then
            echo "$entry"
          fi
        done
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-24
          • 1970-01-01
          • 2015-04-10
          • 2022-06-16
          • 2020-09-11
          • 2014-10-18
          • 2021-02-18
          • 2012-06-25
          相关资源
          最近更新 更多