bash-如何遍历目录中的文件并更改路径并将后缀添加到文件名

查看原始版本

我需要编写一个脚本,用不同的参数启动我的程序,但我是新手。我开始我的程序时:

./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt]

这是我要做的事情的伪代码:

for each filename in /Data do
  for int i = 0, i = 3, i++
    ./MyProgram.exe Data/filename.txt Logs/filename_Log{i}.txt
  end for
end for

所以我真的很困惑如何从第一个参数创建第二个参数,所以看起来像dataABCD\u Log1.txt并启动我的程序。

所有回答
  • Lucien Lee #1

    首先要注意:当您使用Data/data1.txt作为参数时,它真的应该是/Data/data1.txt吗(带有一个前导斜杠)?另外,外循环应该只扫描.txt文件,还是只扫描/Data中的所有文件?这里有一个答案,假设只有/Data/data1.txt和.txt文件:

    #!/bin/bash
    for filename in /Data/*.txt; do
        for ((i=0; i<=3; i++)); do
            ./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
        done
    done
    

    注:

    • /Data/*.txt扩展到/Data中的文本文件路径(包括/Data/part)
    • $( ... )运行shell命令,并在命令行的该点插入其输出
    • basename somepath .txt输出somepath的基本部分,从末尾删除.txt(例如/Data/file.txt>file

    如果需要用Data/file.txt而不是/Data/file.txt运行MyProgram,请使用"${filename#/}"删除前导斜杠。另一方面,如果你想扫描的是Data而不是/Data,只需使用for filename in Data/*.txt

  • Maxine Lee #2

    很抱歉让线程死灵化,但是每当您通过globbing遍历文件时,最好避免glob不匹配的情况(这会使循环变量扩展到(不匹配)glob模式字符串本身)

    例如:

    for filename in Data/*.txt; do
        [ -e "$filename" ] || continue
        # ... rest of the loop body
    done
    

    参考文献:Bash Pitfalls

  • Lyndon Lee #3
    for file in Data/*.txt
    do
        for ((i = 0; i < 3; i++))
        do
            name=${file##*/}
            base=${name%.txt}
            ./MyProgram.exe "$file" Logs/"${base}_Log$i.txt"
        done
    done
    

    name=${file##*/}替换(shell parameter expansion)删除前导路径名,直到最后一个/

    base=${name%.txt}替换将删除后面的.txt。如果扩展名可以改变的话,这就有点棘手了

  • Nigel Lee #4

    可以将finds空分隔输出选项与read一起使用,以安全地在目录结构上迭代

    #!/bin/bash
    find . -type f -print0 | while IFS= read -r -d $'0' file; 
      do echo "$file" ;
    done
    

    所以为了你的案子

    #!/bin/bash
    find . -maxdepth 1 -type f  -print0 | while IFS= read -r -d $'0' file; do
      for ((i=0; i<=3; i++)); do
        ./MyProgram.exe "$file" 'Logs/'"`basename "$file"`""$i"'.txt'
      done
    done
    

    另外

    #!/bin/bash
    while IFS= read -r -d $'0' file; do
      for ((i=0; i<=3; i++)); do
        ./MyProgram.exe "$file" 'Logs/'"`basename "$file"`""$i"'.txt'
      done
    done < <(find . -maxdepth 1 -type f  -print0)
    

    将在脚本(进程)的当前作用域中运行while循环,并允许在需要时将find的输出用于设置变量

  • Gavin Lee #5

    看起来你在尝试执行一个windows文件(.exe),当然你应该使用powershell。无论如何,在Linux bash shell上,一个简单的一行程序就足够了

    [/home/$] for filename in /Data/*.txt; do for i in {0..3}; do ./MyProgam.exe  Data/filenameLogs/$filename_log$i.txt; done done
    

    或是在狂欢中

    #!/bin/bash
    
    for filename in /Data/*.txt; 
       do
         for i in {0..3}; 
           do ./MyProgam.exe Data/filename.txt Logs/$filename_log$i.txt; 
         done 
     done