如何在shell脚本中获取目录中的文件列表?
Posted
技术标签:
【中文标题】如何在shell脚本中获取目录中的文件列表?【英文标题】:How to get the list of files in a directory in a shell script? 【发布时间】: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。
【问题讨论】:
【参考方案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 感谢您的建议!我不知道文件名中允许换行 - 什么样的文件可能有它们?比如,这是经常发生的事情吗? 由于这个原因,文件名中的换行符是邪恶的,据我所知,没有正当理由使用它们。我自己从未在野外见过一只。也就是说,完全有可能通过换行符恶意构造文件名以利用这一点。 (例如,想象一个包含文件A
、B
和C
的目录。您创建名为B\nC
和D
的文件,然后选择删除它们。不处理此权限的软件可能会结束即使您没有这样做的权限,也要删除先前存在的文件 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
【讨论】:
以上是关于如何在shell脚本中获取目录中的文件列表?的主要内容,如果未能解决你的问题,请参考以下文章