我有这个代码:
for file in "$@"*png; do
echo "$file"
done
仅当您提供以 / 结尾的路径时,它才有效/root/
。
在这种情况下,在不破坏我的脚本的情况下将 / 添加到路径输入的正确方法是什么?
如果你给出的路径输入末尾没有 / ,它只会执行以下操作:
File: /root*png
如果我将其修改为for file in "$@"/*png; do
并输入/root/test/
它可以工作,但结果看起来很难看:
File: /root/test//sample2.png
答案1
ilkkachu 指出了我的答案中的一个重大缺陷,并在他的答案中纠正了它,所以请给予他应得的信任。不过我想出了另一个解决方案:
#!/bin/bash
for dir in "$@"; do
find "$dir" -type f -name '*png' -exec readlink -f {} \;
done
例子:
$ ll
total 6
-rwxr-xr-x 1 root root 104 Jan 7 14:03 script.sh*
drwxr-xr-x 2 root root 3 Jan 7 04:21 test1/
drwxr-xr-x 2 root root 3 Jan 7 04:21 test2/
drwxr-xr-x 2 root root 3 Jan 7 04:21 test3/
$ for n in {1..3}; do ll "test$n"; done
total 1
-rw-r--r-- 1 root root 0 Jan 7 04:21 testfile.png
total 1
-rw-r--r-- 1 root root 0 Jan 7 04:21 testfile.png
total 1
-rw-r--r-- 1 root root 0 Jan 7 04:21 testfile.png
$ ./script.sh test1 test2/ test3
/root/temp/test1/testfile.png
/root/temp/test2/testfile.png
/root/temp/test3/testfile.png
原创解决方案:
for file in "${@%/}/"*png; do
echo "$file"
done
${@%/} 会删除参数末尾的 / ,然后 / 外面的 / 会将其添加回来——或者将其添加到任何没有的参数中。
答案2
像这样使用$@
glob 似乎有点奇怪。如果您期望它能够处理多个参数,那么它是行不通的。周围的字符串$@
仅附加到第一个和列表项。
$ mkdir a b; touch a/a.png b/b.png
$ set -- a b
$ echo x"$@"x
xa bx
$ echo "$@/"*.png
a b/b.png
因此,要处理多个参数,您需要"$@"
单独循环:
for arg in "$@"; do
for file in "${arg%/}"/*.png; do
echo "$file"
done
done
在另一种情况下,您可以使用字符串替换扩展${//}
(在 Bash 或 zsh 中)为每个位置参数添加后缀,但要使其与 glob 一起使用相当困难。
答案3
您也可以使用 tr。
始终在末尾添加 / 并...
file='/root/test//sample2.png';echo "$file" | tr -s '/'