这是 Shell 中很常见的需求,不要定义 PATH1、PATH2、PATH3 再一个个处理 ,而是把所有路径放到一个列表中,再用 for 循环。
方法一:使用数组(推荐,bash)
bash
#!/bin/bash
dirs=(
"/tmp/log"
"/home/user/data"
"/opt/test"
)
for dir in "${dirs[@]}"; do
echo "Processing $dir"
if [ -d "$dir" ]; then
ls "$dir"
else
echo "$dir does not exist"
fi
done
优点:
- 路径中可以包含空格
- 易于维护
- 添加路径只需增加一行
方法二:直接在 for 中写路径
如果路径数量不多:
bash
for dir in \
"/tmp/log" \
"/home/user/data" \
"/opt/test"
do
echo "$dir"
done
方法三:变量保存多个路径
bash
DIRS="/tmp/log /home/user/data /opt/test"
for dir in $DIRS
do
echo "$dir"
done
注意:
这种方法不能处理包含空格的路径,例如:
/home/user/my dir
会被拆成两个字符串。
方法四:从文件读取
例如 dirs.txt
text
/tmp/log
/home/user/data
/opt/test
脚本:
bash
while IFS= read -r dir
do
echo "$dir"
done < dirs.txt
适合路径很多的时候。
如果你的环境是 tcsh
由于你之前提到经常使用 tcsh,写法有所不同:
tcsh
set dirs = ( \
/tmp/log \
/home/user/data \
/opt/test \
)
foreach dir ($dirs)
echo $dir
if ( -d $dir ) then
ls $dir
else
echo "$dir does not exist"
endif
end
推荐
- bash :使用数组(方法一)。
- tcsh :使用
set dirs = (...)+foreach。
这两种方式都是最清晰、最容易维护的写法。
如果每个目录都有一个对应的文件名,最好的做法是把它们成对保存,而不是分别保存两个列表,否则容易对应错。
方法一:两个数组(bash,推荐)
bash
#!/bin/bash
dirs=(
"/tmp/log1"
"/tmp/log2"
"/tmp/log3"
)
files=(
"run.log"
"error.log"
"debug.log"
)
for ((i=0; i<${#dirs[@]}; i++)); do
dir="${dirs[i]}"
file="${files[i]}"
echo "Processing: $dir/$file"
if [ -f "$dir/$file" ]; then
cat "$dir/$file"
else
echo "$dir/$file does not exist"
fi
done
输出类似:
Processing: /tmp/log1/run.log
Processing: /tmp/log2/error.log
Processing: /tmp/log3/debug.log
方法二:把目录和文件名写在一起(更推荐)
如果它们是一一对应的,可以直接保存完整路径:
bash
paths=(
"/tmp/log1/run.log"
"/tmp/log2/error.log"
"/tmp/log3/debug.log"
)
for path in "${paths[@]}"; do
echo "$path"
if [ -f "$path" ]; then
cat "$path"
fi
done
这是最简单、最不容易出错的方式。
方法三:关联关系(键值对)
如果一个目录始终对应一个文件,可以用关联数组(需要 Bash 4+):
bash
declare -A logs
logs["/tmp/log1"]="run.log"
logs["/tmp/log2"]="error.log"
logs["/tmp/log3"]="debug.log"
for dir in "${!logs[@]}"; do
file="${logs[$dir]}"
echo "$dir/$file"
done
如果你使用的是 tcsh
tcsh 没有数组索引和关联数组那么方便,通常用两个列表:
tcsh
set dirs = ( /tmp/log1 /tmp/log2 /tmp/log3 )
set files = ( run.log error.log debug.log )
@ i = 1
while ( $i <= $#dirs )
echo "$dirs[$i]/$files[$i]"
@ i++
end
推荐选择
根据你之前的问题,你主要写的是 bash 脚本,因此建议:
- 如果目录和文件名固定对应:直接保存完整路径(方法二),最简洁。
- 如果目录和文件名后续可能分别使用:使用两个数组,通过相同索引对应(方法一),可维护性最好。