在bash脚本中循环使用多个元素而不是一个元素

时间:2017-09-06 16:46:06

标签: bash shell for-loop ubuntu-16.04

我一直在关注这些问题中给出的答案

  

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包含所有以空格分隔的文件名。但我希望一次得到一个。这可能是什么问题?

3 个答案:

答案 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