【问题标题】:How to pass variable (list of folders) to for-loop?如何将变量(文件夹列表)传递给for循环?
【发布时间】:2012-05-11 14:02:04
【问题描述】:

我是 Linux 的新手,也是编程的初学者,但已经能够将几行代码拼凑在一起 here 用于将文件列表传递给 for 循环,here 用于对文件夹做同样的事情。

# Run search.sh from base folder; 
# Only interested in folders under base folder (e.g., baseFolder/FolderA)
# list all folders in base directory that match search parameters;
# cut out just the folder name; feed to variable DIR

 DIR=$(find . -name *MTL.txt | cut -d '/' -f2)

# echo $DIR = "FolderA FolderB FolderC"
# place that information in a for-loop

    for i in $DIR; do

      cd $DIR # step into folder

      # find specific file in folder for processing
      FILE=$(find -name *MTL | cut -d '/' -f2)

      # copy in a static file from another folder;
      # rename file based on file name found in previous step
      cp /baseFolder/staticfile.txt $FILE.new
      do more stuff

      cd .. # step out of directory

     done

第一个目录的代码可以正常完成,但无法移动到后续目录。我猜我的(许多)问题之一是我不能像我一样将文件夹名称列表传递给 $DIR 。这应该很简单,但我的 foo 很弱。

请老师给我指路。

编辑:

将“cd $DIR”更改为“cd $i”具有预期的效果。代码现在循环遍历所有目录并在每个目录中正确执行操作。 - 感谢 core1024 标记上述内容。

【问题讨论】:

  • 顺便说一句......你不要错过一个点'。'在 'FILE=$(find -name *MTL | cut -d '/' -f2) ' 之后 'find'?
  • 我不是专家,但我认为cd $DIR # step into folder应该是cd $i # step into folder
  • @core1024:我只是面对手掌。在我的代码中更改这件小事使一切正常!您可以发布作为答案吗?谢谢。
  • @SkippyFastol:我删除了“。”在 find 命令中,这两种方式都没有区别。我的理解是,它是为了将 find 命令保留在当前目录中?

标签: bash for-loop


【解决方案1】:

cd .. # 跳出目录

只需提升一个级别。

在循环之前,您需要将“基本目录”存储在变量中:

BASEDIR=`pwd`

然后,你将执行

cd $BASEDIR # step out of directory

而不是你现在的

cd ..

【讨论】:

  • 根据他生成DIR 的方式,他对cd 的深度永远不会超过一级。
  • @chepner:既然你提到了它......但这并没有让我的建议不那么合法:)
【解决方案2】:

我不是专家,但我认为cd $DIR # step into folder 应该是cd $i # step into folder

【讨论】:

    【解决方案3】:

    不过,不需要“For 循环”。 find 命令已经循环遍历它找到的所有项目。

    find 命令上有一个 -exec 选项,可将“找到”的每个项目传递给特定命令。

    例如

    find . -name *MTL.txt -exec cp {} /basefolder \;
    

    这会将找到的所有文件复制到 /basefolder

    如果您对使用 for 循环有强烈的感觉,您还可以将命令的输出用作循环列表。

    例如

    for MYVAR in `ls *.txt* `
    do
        echo $MYVAR
    done
    

    除非您正在格式化输出或有一个不将其输出发送到标准输出的命令,否则使用 cut 通常不是一个好主意。

    【讨论】:

    • 永远,永远for var in `ls`Seriouslyfor MYVAR in *.txt*
    【解决方案4】:

    下面稍微简单一些,因为它不需要解析find输出:

    for subdir in *; do
      if [[ ! -d $subdir ]]; then
        continue
      fi
    
      cd $subdir
      for f in *MTL.txt; do
        cp /baseFolder/staticFile.txt $f.new
        # And whatever else
      done
    
      cd ..
    done
    

    请注意,我只进入每个子目录一次,而您的原始代码会在其中执行多次。我指出这一点,以防这是你的意图。此外,由于您的 cut 命令阻止您深入一个以上的目录,我认为这是您的意图。

    根据您所做的其他事情,您可能能够完全避免更改目录。例如:

    for f in $subdir/*MTL.txt; do
      cp /baseFolder/staticFile.txt $f.new
      # More stuff
    done
    

    【讨论】:

      【解决方案5】:

      如果目录名称包含空格,您的原始代码将中断。并且如果您在一个目录中有多个满足查找条件的文件,您还将重复该操作。 替代方案:

      IFS='
      '
      declare -a DIR
      declare -a FILE
      DIR=($(find . -name '*MTL.txt' | cut -f2 -d '/' | uniq))
      for x in "${DIR[@]}"
       do
         if [ -d "$x" ];  then
           pushd "$x"
              FILE=($(ls *MTL))
              for y in "${FILE[@]}"
                do
                  cp /baseFolder/staticfile.txt  "$y"
                  echo do more stuff
                done
           popd
         fi
       done
      

      【讨论】:

      • ls 不是必需的。 FILE=(*)
      猜你喜欢
      • 1970-01-01
      • 2019-03-31
      • 2014-10-05
      • 2017-04-01
      • 2021-05-31
      • 1970-01-01
      • 2019-11-29
      • 2021-06-21
      • 1970-01-01
      相关资源
      最近更新 更多