如何获取shell脚本中目录中的文件列表?

jrh*_*ath 134 bash shell directory-listing

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

我的脚本是:

for entry in `ls $search_dir`; do
    echo $entry
done
Run Code Online (Sandbox Code Playgroud)

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

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

我知道我可以更改到该目录,for entry in *然后使用然后更改回来,但我的特殊情况阻止我这样做.

我有两个相对路径$search_dir$work_dir,和我有两个同时工作,阅读他们创建/删除在他们的文件等.

那我现在该怎么办?

PS:我用bash.

Ign*_*ams 232

for entry in "$search_dir"/*
do
  echo "$entry"
done
Run Code Online (Sandbox Code Playgroud)

  • @mrgloom:因为你需要让shell为通配符. (6认同)
  • 这对我来说不适用于macos (4认同)
  • 如果文件夹为空或者某些文件以句点开头,则此操作不起作用(在使用默认设置的 bash 中)。 (4认同)
  • 您能解释一下为什么在“ $ search_dir / *”中的输入无效吗?为什么我们需要将“ / *”放在引号之外? (3认同)
  • 解决方案给出了完整的路径。如果我只想列出当前目录中的内容怎么办? (3认同)
  • @mrgloom 如果你想这样做,你可以使用 `for entry in "${search_dir}/*"` 来实现 (2认同)
  • @Anish B:停止破坏原始帖子。答案是正确的,正如所写的那样 (2认同)

teg*_*gan 24

这里的其他答案很棒,并回答你的问题,但这是"bash获取目录中的文件列表"的最佳谷歌结果,(我一直在寻找保存文件列表)所以我想我会发布一个回答这个问题:

ls $search_path > filename.txt
Run Code Online (Sandbox Code Playgroud)

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

ls $search_path | grep *.txt > filename.txt
Run Code Online (Sandbox Code Playgroud)

请注意,$ search_path是可选的; ls> filename.txt将执行当前目录.

  • @samurai_jane 关于此主题有很多链接可供提供,但这是第一个搜索结果:https://mywiki.wooledge.org/ParsingLs。我什至在这里看到了一个关于 SO 的问题,声称不解析 ls 输出的原因是废话,并且对此非常详尽。但回复/答案仍然声称这是一个坏主意。看看:https://unix.stackexchange.com/questions/128985/why-not-parse-ls-and-what-do-to-instead (3认同)
  • 无需使用 grep 只获取 .txt 文件:`ls $search_path/*.txt > filename.txt'。但更重要的是,不应使用 ls 命令的输出来解析文件名。 (2认同)

rrr*_*rrr 20

这是一种方法,我可以更简单地理解语法:

yourfilenames=`ls ./*.txt`
for eachfile in $yourfilenames
do
   echo $eachfile
done
Run Code Online (Sandbox Code Playgroud)

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

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

  • https://mywiki.wooledge.org/ParsingLs 解释了这种方法的大量陷阱。基本上你不应该在脚本中使用“ls”。无论如何,这很愚蠢;当“ls”运行时,shell 已经扩展了通配符。 (2认同)

gho*_*g74 17

for entry in "$search_dir"/* "$work_dir"/*
do
  if [ -f "$entry" ];then
    echo "$entry"
  fi
done
Run Code Online (Sandbox Code Playgroud)


Noe*_*Yap 11

find "${search_dir}" "${work_dir}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 -I {} echo "{}"
Run Code Online (Sandbox Code Playgroud)

  • 为什么你用`xargs`?默认情况下,`find`打印它找到的内容......你可以删除`-print0`中的所有内容. (3认同)
  • 我知道这已经很老了,但我似乎无法得到最后一个 `xargs -0 -i echo "{}"` 命令,愿意解释一下吗?特别是 `-i echo "{}"` 部分是做什么的?我还从“man”页面读到“-i”现在已被弃用,我们应该使用“-I”插入。 (2认同)

Vic*_*art 9

$ 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
Run Code Online (Sandbox Code Playgroud)

变化

$ 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
Run Code Online (Sandbox Code Playgroud)

笔记:

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


Kol*_*an1 5

与接受的答案类似 - 但仅列出文件名而不是完整路径:

这似乎已经在不久前得到了回答,但我想我还想提供一个答案,仅列出所需目录中的文件,而不是完整路径。

    #search_dir=/the/path/to/base/dir/
    IFS=$'\n' #for in $() splits based on IFS
    search_dir="$(pwd)"
    for entry in $(ls $search_dir)
    do
        echo $entry
    done
Run Code Online (Sandbox Code Playgroud)

如果您还想过滤特定文件,您可以添加一条grep -q语句。

    #search_dir=/the/path/to/base/dir/
    IFS=$'\n' #for in $() splits based on IFS
    search_dir="$(pwd)"
    for entry in $(ls $search_dir)
    do
        if grep -q "File should contain this entire string" <<< $entry; then
        echo "$entry"
        fi
    done
Run Code Online (Sandbox Code Playgroud)

参考:

有关 IFS 的更多信息可在此处找到。

有关在 shell 中查找子字符串的更多信息,请参阅此处