我有一段代码可以回显文件夹中的文件,该文件夹由两个变量描述。 这很好并且有效。 但是,我现在想列出另一个文件夹结构上的文件。但是我无法将其列出。
DIRS="foo bar live1 live2"
SRCDIR="/mnt/nas/stage/live/live/"
# iterate over all directories
for dirname in "${DIRS}"; do
# go to source sync directory
cd "${SRCDIR}/${dirname}"
# get latest mux file name
filename=`ls -t *.mux 2>/dev/null |head -n 1`
echo $filename
###There is additional code to work on the files here that uses $dirname
done
然后我想添加另一个目录结构;
DIRS1="foo bar live1 live2"
SRCDIR1="/mnt/nas/stage/live/live/"
DIRS2="test1 test2"
SRCDIR2="/mnt/nas/stage/test/test/"
我必须
for dirname in ${DIRS1} ${DIRS2}
当我收到“没有这样的文件或目录”错误时,这有效,
但后来我无法将 CD 变量更改为 SRCDIR2,我确实想再放一个 for 循环
for dirpath in ${SRCDIR1} ${SRCDIR2}
cd "${dirpath}/${dirname}"
然而,这给出了笛卡尔响应。我怎样才能分开只让 DIR1 在 SRCDIR1 中查找,而 DIR2 在 SRCDIR2 中查找?
查看其他答案,我可能需要使用数组,但不知道如何将其放入代码中。
如果您知道目录名称不包含空格,您可以使用一对数组,例如:
DIRS[1]="foo bar live1 live2"
SRCDIR[1]="/mnt/nas/stage/live/live/"
DIRS[2]="test1 test2"
SRCDIR[2]="/mnt/nas/stage/test/test/"
for ((id=1; id<=2; id++))
do
for dir in ${DIRS[id]} # no double quotes so that each entry is processed separately
do
echo "${SRCDIR[id]}${dir}"
done
done
这会生成:
/mnt/nas/stage/live/live/foo
/mnt/nas/stage/live/live/bar
/mnt/nas/stage/live/live/live1
/mnt/nas/stage/live/live/live2
/mnt/nas/stage/test/test/test1
/mnt/nas/stage/test/test/test2
如果目录名称可能包含空格,则此解决方案(不带引号的
${DIRS[id]}
)不起作用,请考虑:
DIRS[1]="foo bar live1 live2 'foo bar live{1,2}'" # 5th entry contains a pair of spaces
SRCDIR[1]="/mnt/nas/stage/live/live/"
DIRS[2]="test1 test2"
SRCDIR[2]="/mnt/nas/stage/test/test/"
for ((id=1; id<=2; id++))
do
for dir in ${DIRS[id]} # split on whitespace
do
echo "${SRCDIR[id]}${dir}"
done
done
这会生成:
/mnt/nas/stage/live/live/foo
/mnt/nas/stage/live/live/bar
/mnt/nas/stage/live/live/live1
/mnt/nas/stage/live/live/live2
/mnt/nas/stage/live/live/'foo # 5th entry
/mnt/nas/stage/live/live/bar # broken into
/mnt/nas/stage/live/live/live{1,2}' # 3 parts
/mnt/nas/stage/test/test/test1
/mnt/nas/stage/test/test/test2
如果目录名称可以包含空格,那么另一种方法是使用硬编码数组名称和名称引用(
declare -n
),例如:
DIRS1=(foo bar live1 live2 'foo bar live{1,2}') # 5th entry contains a pair of spaces
SRCDIR1="/mnt/nas/stage/live/live/"
DIRS2=(test1 test2)
SRCDIR2="/mnt/nas/stage/test/test/"
for ((id=1; id<=2; id++))
do
declare -n dirs="DIRS${id}" # nameref; 1st time dirs is a pointer to DIRS1
declare -n srcdir="SRCDIR${id}" # nameref; 1st time srcdir is a pointer to SRCDIR1
for dir in "${dirs[@]}"
do
echo "${srcdir}${dir}"
done
done
注意: namerefs 需要
bash 4.3+
这会生成:
/mnt/nas/stage/live/live/foo
/mnt/nas/stage/live/live/bar
/mnt/nas/stage/live/live/live1
/mnt/nas/stage/live/live/live2
/mnt/nas/stage/live/live/foo bar live{1,2} # 5th entry maintains whitespace
/mnt/nas/stage/test/test/test1
/mnt/nas/stage/test/test/test2
正如评论中提到的,理想的解决方案是一对多维数组(例如,
DIRS[1,1]="foo"
);不幸的是 bash
不支持多维数组。
是的,可以通过索引串联来模拟多维数组(例如,
DIRS[1-1]="foo"
),但必要的代码有点混乱。如果感兴趣的话,我会把它留给OP来研究这个想法......
考虑到 Bash 数组和关联数组的局限性,以及与间接使用变量相关的许多陷阱,我会考虑使用类似这样的 Shellcheck-clean 代码:
#! /bin/bash -p
# SRCDIR DIRS
# -------------------------- -----------------------
srcdir_dirs=( /mnt/nas/stage/live/live foo bar live1 live2 ''
/mnt/nas/stage/test/test 'test 1' 'test 2' '' )
srcdir='' dirname=''
for d in "${srcdir_dirs[@]}"; do
if [[ -z $d ]]; then
srcdir=''
elif [[ -z $srcdir ]]; then
srcdir=$d
else
dirname=$d
printf '%s/%s\n' "$srcdir" "$dirname"
# ...
fi
done
test1
和 test2
替换为 test 1
和 test 2
,以证明包含空格的名称不会导致问题。 即使名称中换行也可以。''
中的空字符串 (srcdir_dirs
) 条目分隔定义源目录和多个子目录的条目组。 这是安全的,因为空字符串不是有效的文件或目录名称或路径。srcdir_dirs
数组可以轻松扩展以处理三个或更多源目录。printf
而不是 echo
。