Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 循环遍历使用参数指定的目录中的文件_Bash_Shell_Posix - Fatal编程技术网

Bash 循环遍历使用参数指定的目录中的文件

Bash 循环遍历使用参数指定的目录中的文件,bash,shell,posix,Bash,Shell,Posix,我正在尝试循环遍历目录中的文件,其中目录作为参数传递。我当前在test.sh中保存了以下脚本: #!/bin/bash for filename in "$1"/*; do echo "File:" echo $filename done 我正在使用以下命令运行上述命令: sh test.sh path/to/loop/over 但是,上面没有输出目录path/to/loop/over中的文件,而是输出: File: path/to/l

我正在尝试循环遍历目录中的文件,其中目录作为参数传递。我当前在
test.sh中保存了以下脚本:

#!/bin/bash
for filename in "$1"/*; do
    echo "File:"
    echo $filename
done
我正在使用以下命令运行上述命令:

sh test.sh path/to/loop/over
但是,上面没有输出目录
path/to/loop/over
中的文件,而是输出:

File:
path/to/loop/over/*
我猜它将
path/to/loop/over/*
解释为字符串而不是目录。我的预期输出如下:

File:
foo.txt
File:
bar.txt

其中
foo.txt
bar.txt
path/to/loop/over/
目录中的文件。我发现建议在
$1
之后添加
/*
,但是,这似乎没有帮助(也没有帮助)

如果目录为空或拼写错误,就会发生这种情况。如果没有匹配项,shell(在其默认配置中)就不会扩展通配符。(您可以在Bash中使用
shopt-s nullglob
控制此操作;使用此选项,只需删除与任何内容都不匹配的通配符。)

您可以自己轻松地验证这一点。在包含四个文件的目录中

sh$echo*
一两个文件
sh$echo[ot]*
一两个
sh$ECHON*
n*
在Bash

bash$echo n*
n*
bash$shopt-s nullglob
bash$echon*
我猜您对当前工作目录如何影响目录名的解析感到困惑;可以阅读

迭代目录的内容 兼容答案(不仅仅是bash) 标记此问题时,有一种POSIX兼容方式:

就足够了(使用包含空格的文件名):

使用any可以很好地执行此操作。使用
bash
ksh
dash
zsh
busybox sh
进行测试

#!/bin/sh

cd "$1" || exit 1
for file in * ;do
    [ -f "$file" ] && echo "Process '$file'."
done
此版本不会打印路径:

$ myscript.sh /path/to/dir
Process 'foo'.
Process 'bar'.
Process 'foo bar'.
一些方法 介绍 我不喜欢在不需要的时候使用
shopt
。。。(本标准变更) bash行为并减少脚本的可读性)

使用标准bash有一种优雅的方法来实现这一点,而不需要
shopt

当然,前面的答案在下面很好,但是。有一些 InterTesting是一种使脚本更强大、灵活、美观、详细的方法

样品 说明:考虑全局文件与真实文件 执行以下操作时:

files=(/path/to/dir/*)
变量
$files
成为一个数组,包含
/path/to/dir/
下包含的所有文件:

declare -p files
declare -a files=([0]="/path/to/dir/bar" [1]="/path/to/dir/baz" [2]="/path/to/dir/foo")
但如果没有匹配全局模式的,则不会替换星号,阵列将变为:

declare -p files
declare -a files=([0]="/path/to/dir/*")
从那里开始。查找
$文件
类似于查找
${files[0]}
即:数组中的第一个字段。所以

将执行
die
功能,除非数组
files
第一个字段是文件(
[-e“$files”]
以检查现有的条目
[-d“$files”]
要检查现有的目录、ans等…请参阅
man bash
帮助测试

但是您可以用一些基于字符串的测试来代替这个文件系统测试,例如:

[ "$files" = "/path/to/dir/*" ] && die "No files found."
或者,使用数组长度:

((${#files[@]}==1)) && [ "${files##*/}" = "*" ] && die "No files found."

正确引用
“$1”
declare -p files
declare -a files=([0]="/path/to/dir/*")
[ -f "$files" ] || die "No files found."
[ "$files" = "/path/to/dir/*" ] && die "No files found."
((${#files[@]}==1)) && [ "${files##*/}" = "*" ] && die "No files found."