gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 23:45:59 24 4
gpt4 key购买 nike

我试图遍历目录中的文件,目录作为参数传递。我目前在 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.txtbar.txtpath/to/loop/over/ 目录下的文件。我找到了 this answer建议在 $1 之后添加一个 /*,但是,这似乎没有帮助(these suggestions 也没有)

最佳答案

遍历目录内容

兼容的答案(不仅是 bash)

因为这个问题被标记为 ,有一种POSIX 兼容的方式:

#!/bin/sh

for file in "$1"/* ;do
[ -f "$file" ] && echo "Process '$file'."
done

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

$ myscript.sh /path/to/dir
Process '/path/to/dir/foo'.
Process '/path/to/dir/bar'.
Process '/path/to/dir/foo bar'.

这通过使用any 效果很好 .使用 bash 测试, ksh , dash , zshbusybox 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 .

当然,以前的答案在 下工作正常, 但。有一些使您的脚本更强大、更灵活、更漂亮、更详细的有趣方式...

示例

#!/bin/bash

die() { echo >&2 "$0 ERROR: $@";exit 1;} # Emergency exit function

[ "$1" ] || die "Argument missing." # Exit unless argument submitted

[ -d "$1" ] || die "Arg '$1' is not a directory." # Exit if argument is not dir

cd "$1" || die "Can't access '$1'." # Exit unless access dir.

files=(*) # All files names in array $files

[ -f "$files" ] || die "No files found." # Exit if no files found

for file in "${files[@]}";do # foreach file:
echo Process "$file" # Process file
done

说明:考虑globbing真实文件

做的时候:

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")

但是如果没有任何东西匹配 glob 模式,星号将不会被替换并且数组变为:

declare -p files
declare -a files=([0]="/path/to/dir/*")

从那里开始。正在寻找 $files就像在寻找 ${files[0]}即:数组中的第一个字段。所以

[ -f "$files" ] || die "No files found."

将执行die函数除非数组的第一个字段 files是一个文件([ -e "$files" ] 用于检查现有的条目[ -d "$files" ] 用于检查现有的目录,等等...请参阅man bashhelp test )。

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

[ "$files" = "/path/to/dir/*" ] && die "No files found."

或者,使用数组长度:

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

使用参数扩展删除路径:

用于抑制文件名中的路径,而不是cd $path你可以这样做:

targetPath=/path/to/dir
files=($targetPath/*)
[ -f "$files" ] || die "No files found."

然后:

declare -p files
declare -a files=([0]="/path/to/dir/bar" [1]="/path/to/dir/baz" [2]="/path/to/dir/foo")

你可以

printf 'File: %s\n' ${files[@]#$targetPath/}
File: bar
File: baz
File: foo

关于bash - 循环遍历使用参数指定的目录中的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64165943/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com