bash 循环脚本中的多个元素而不是一个
Multiple elements instead of one in bash script for loop
我一直在关注这些问题中给出的答案
Shellscript Looping Through All Files in a Folder
How to iterate over files in a directory with Bash?
编写一个 bash 脚本,遍历文件夹中的文件并处理它们。所以,这是我的代码:
#!/bin/bash
YEAR="2002/"
INFOLDER="/local/data/datasets/Convergence/"
for f in "$INFOLDER$YEAR*.mdb";
do
echo $f
absname=$INFOLDER$YEAR$(basename $f)
# ... the rest of the script ...
done
我收到这个错误:basename: extra operand.
我添加了 echo $f
,我意识到 f
包含 所有文件名,由 space 分隔。但我希望一次得到一个。这可能是什么问题?
只要引用您的 shell 变量,如果它们 应该 包含中间有空格的字符串。
basename "$f"
不这样做会导致将字符串拆分为单独的字符 (see WordSplitting in bash
),从而弄乱需要一个字符串参数而不是多个字符串参数的 basename
命令。
此外,将 *
包含在双引号之外是明智的,因为 shell 通配在它们内部不起作用(单引号或双引号)。
#!/bin/bash
# good practice to lower-case variable names to distinguish them from
# shell environment variables
year="2002/"
in_folder="/local/data/datasets/Convergence/"
for file in "${in_folder}${year}"*.mdb; do
# break the loop gracefully if no files are found
[ -e "$file" ] || continue
echo "$file"
# Worth noting here, the $file returns the name of the file
# with absolute path just as below. You don't need to
# construct in manually
absname=${in_folder}${year}$(basename "$file")
done
只需从这一行中删除“”
对于“$INFOLDER$YEAR*.mdb”中的 f;
看起来像这样
#!/bin/bash
YEAR="2002/"
INFOLDER="/local/data/datasets/Convergence/"
for f in $INFOLDER$YEAR*.mdb;
do
echo $f
absname=$INFOLDER$YEAR$(basename $f)
# ... the rest of the script ...
done
您 运行 遇到了引用问题。在shell中,双引号防止分词和通配符扩展;通常,您不希望这些事情发生在变量的值上,因此您应该对变量引用加双引号。但是当你有一些东西 应该 分词或通配符扩展时,它 不能 被双引号。在您的 for
语句中,您将整个文件模式用双引号引起来:
for f in "$INFOLDER$YEAR*.mdb";
...这可以防止对变量值进行分词和通配符扩展(好),但也可以防止它在 *
上,您 需要 扩展(这就是循环的重点)。所以需要有选择地引用,变量在引号内,通配符在引号外:
for f in "$INFOLDER$YEAR"*.mdb;
然后在循环内,您应该双引号引用 $f
以防任何文件名包含空格或通配符(这在文件名中是完全合法的):
echo "$f"
absname="$INFOLDER$YEAR$(basename "$f")"
(注意:实际上不需要 absname
赋值周围的双引号——赋值的右侧是 shell 中为数不多的安全位置之一跳过它们——但在我看来,将所有变量引用和 $( )
表达式加双引号比试图跟踪安全和不安全的地方更容易和更安全。)
我一直在关注这些问题中给出的答案
Shellscript Looping Through All Files in a Folder
How to iterate over files in a directory with Bash?
编写一个 bash 脚本,遍历文件夹中的文件并处理它们。所以,这是我的代码:
#!/bin/bash
YEAR="2002/"
INFOLDER="/local/data/datasets/Convergence/"
for f in "$INFOLDER$YEAR*.mdb";
do
echo $f
absname=$INFOLDER$YEAR$(basename $f)
# ... the rest of the script ...
done
我收到这个错误:basename: extra operand.
我添加了 echo $f
,我意识到 f
包含 所有文件名,由 space 分隔。但我希望一次得到一个。这可能是什么问题?
只要引用您的 shell 变量,如果它们 应该 包含中间有空格的字符串。
basename "$f"
不这样做会导致将字符串拆分为单独的字符 (see WordSplitting in bash
),从而弄乱需要一个字符串参数而不是多个字符串参数的 basename
命令。
此外,将 *
包含在双引号之外是明智的,因为 shell 通配在它们内部不起作用(单引号或双引号)。
#!/bin/bash
# good practice to lower-case variable names to distinguish them from
# shell environment variables
year="2002/"
in_folder="/local/data/datasets/Convergence/"
for file in "${in_folder}${year}"*.mdb; do
# break the loop gracefully if no files are found
[ -e "$file" ] || continue
echo "$file"
# Worth noting here, the $file returns the name of the file
# with absolute path just as below. You don't need to
# construct in manually
absname=${in_folder}${year}$(basename "$file")
done
只需从这一行中删除“” 对于“$INFOLDER$YEAR*.mdb”中的 f;
看起来像这样
#!/bin/bash
YEAR="2002/"
INFOLDER="/local/data/datasets/Convergence/"
for f in $INFOLDER$YEAR*.mdb;
do
echo $f
absname=$INFOLDER$YEAR$(basename $f)
# ... the rest of the script ...
done
您 运行 遇到了引用问题。在shell中,双引号防止分词和通配符扩展;通常,您不希望这些事情发生在变量的值上,因此您应该对变量引用加双引号。但是当你有一些东西 应该 分词或通配符扩展时,它 不能 被双引号。在您的 for
语句中,您将整个文件模式用双引号引起来:
for f in "$INFOLDER$YEAR*.mdb";
...这可以防止对变量值进行分词和通配符扩展(好),但也可以防止它在 *
上,您 需要 扩展(这就是循环的重点)。所以需要有选择地引用,变量在引号内,通配符在引号外:
for f in "$INFOLDER$YEAR"*.mdb;
然后在循环内,您应该双引号引用 $f
以防任何文件名包含空格或通配符(这在文件名中是完全合法的):
echo "$f"
absname="$INFOLDER$YEAR$(basename "$f")"
(注意:实际上不需要 absname
赋值周围的双引号——赋值的右侧是 shell 中为数不多的安全位置之一跳过它们——但在我看来,将所有变量引用和 $( )
表达式加双引号比试图跟踪安全和不安全的地方更容易和更安全。)