我一直在关注这些问题中给出的答案
编写一个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
包含所有以空格分隔的文件名。但我希望一次得到一个。这可能是什么问题?
答案 0 :(得分:2)
只要引用你的shell变量,如果它们假设包含其间有空格的字符串。
basename "$f"
不执行此操作会导致将字符串拆分为单独的字符(see WordSplitting in bash
),从而弄乱basename
命令,该命令需要一个字符串参数而不是多个。
同样明智的做法是将*
包含在双引号之外,因为shell globbing不会在其中工作(单引号或双引号)。
#!/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
答案 1 :(得分:2)
您在引用方面遇到问题。在shell中,双引号可防止字拆分和通配符扩展;通常,您不希望这些事情发生在变量值上,因此您应该双引号变量引用。但是当你有应该分词或通配符扩展的东西时,不能被双引号。在for
语句中,您将整个文件模式用双引号:
for f in "$INFOLDER$YEAR*.mdb";
...它可以防止变量上的分词和通配符扩展。值(好)但也阻止了你需要扩展的*
(这是循环的重点)。所以你需要有选择地引用,引号内的变量和它们之外的通配符:
for f in "$INFOLDER$YEAR"*.mdb;
然后在循环内部,如果任何文件名包含空格或通配符(在文件名中完全合法),则应该引用$f
的引用:
echo "$f"
absname="$INFOLDER$YEAR$(basename "$f")"
(注意:absname
赋值的双引号实际上并不需要 - 作业的右侧是shell中安全的少数几个地方之一跳过它们 - 但IMO更容易和更安全,只是双引号所有变量引用和$( )
表达式,而不是试图跟踪它的安全位置和它在哪里“#”;不是。)
答案 2 :(得分:0)
从此行中删除“” for f in“$ INFOLDER $ YEAR * .mdb”;
所以它看起来像这样
#!/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