【问题标题】:How can I manipulate file names using bash and sed?如何使用 bash 和 sed 操作文件名?
【发布时间】:2011-08-30 12:02:05
【问题描述】:

我正在尝试遍历目录中的所有文件。

我想对每个文件做一些事情(将其转换为 xml,不包括在示例中),然后将文件写入新的目录结构。

for file in `find /home/devel/stuff/static/ -iname "*.pdf"`;
do
  echo $file;
  sed -e 's/static/changethis/' $file > newfile +".xml";
  echo $newfile;
done

我希望结果是:

$file => /home/devel/stuff/static/2002/hello.txt

$newfile => /home/devel/stuff/changethis/2002/hello.txt.xml

如何更改我的sed 行?

【问题讨论】:

    标签: bash shell sed


    【解决方案1】:

    如果您需要重命名多个文件,我建议使用rename 命令:

    # remove "-n" after you verify it is what you need
    rename -n 's/hello/hi/g' $(find /home/devel/stuff/static/ -type f)
    

    或者,如果你没有rename,试试这个:

    find /home/devel/stuff/static/ -type f | while read FILE
    do
        # modify line below to do what you need, then remove leading "echo" 
        echo mv $FILE $(echo $FILE | sed 's/hello/hi/g')
    done
    

    【讨论】:

      【解决方案2】:

      您是否要更改文件名?那么

      for file in /home/devel/stuff/static/*/*.txt
      do
          echo "Moving $file"
          mv "$file" "${file/static/changethis}.xml"
      done
      

      在使用脚本之前,请确保 /home/devel/stuff/static/*/*.txt 是您想要的。

      【讨论】:

      • 没有。我正在尝试获取文件名,附加“.xml”并将其放在 diff 目录中
      • @木乔:你的通配符扩展会漏掉静态目录下的任何.txt文件。 find 命令不会。
      • @Hai Vu,是的,没错。但我实际上不知道该操作是否在静态目录中有任何 txt 文件。这也是我让他确认路径是否正确的部分原因。
      【解决方案3】:

      首先,您必须根据初始文件的名称创建新文件的名称。显而易见的解决方案是:

      newfile=${file/static/changethis}.xml
      

      其次,您必须确保新目录存在,如果不存在则创建它:

      mkdir -p $(dirname $newfile)
      

      然后你可以对你的文件做一些事情:

      doSomething < $file > $newfile
      

      【讨论】:

        【解决方案4】:

        我不会执行for 循环,因为可能会使您的命令行超载。命令行的长度是有限的,如果你超载它,它会简单地删除多余的部分,而不会给你任何警告。如果您的 find 返回 100 个文件,它可能会起作用。如果它返回 1000 个文件,它可能会工作,但如果你的 find 返回 1000 个文件,它可能会失败,而你永远不会知道。

        处理此问题的最佳方法是将 find 传递到 while read 语句中,如 glenn jackman

        sed 命令仅适用于 STDIN 和文件,但不适用于文件名,因此如果您想修改文件名,则必须执行以下操作:

        $newname="$(echo $oldname | sed 's/old/new/')"
        

        获取文件的新名称。 $() 构造执行命令并将命令的结果放在 STDOUT 上。

        因此,您的脚本将如下所示:

        find /home/devel/stuff/static/ -name "*.pdf" | while read $file
        do
            echo $file;
            newfile="$(echo $file | sed -e 's/static/changethis/')"
            newfile="$newfile.xml"
            echo $newfile;
         done
        

        现在,由于您要重命名文件目录,因此您必须在移动或复制之前确保该目录存在:

        find /home/devel/stuff/static/ -name "*.pdf" | while read $file
        do
            echo $file;
            newfile="$(echo $file | sed -e 's/static/changethis/')"
            newfile="$newfile.xml"
            echo $newfile;
        
            #Check for directory and create it if it doesn't exist
            $dirname=$(dirname "$newfile")
            if [ ! -d "$dirname" ]
            then
                mkdir -p "$dirname"
            fi
        
            #Directory now exists, so you can do the move
            mv "$file" "$newfile"
         done
        

        注意引号以处理文件名中有空格的情况。

        顺便说一句,不要这样做:

        if [ ! -d "$dirname" ]
        then
            mkdir -p "$dirname"
        fi
        

        你可以这样做:

        [ -d "$dirname"] || mkdir -p "$dirname"
        

        || 表示只有在测试不成立时才执行以下命令。因此,如果 [ -d "$dirname" ] 是错误语句(目录不存在),则运行 mkdir

        当您看到 shell 脚本时,这是一个相当常见的快捷方式。

        【讨论】:

          【解决方案5】:
          find ... | while read file; do
            newfile=$(basename "$file").xml;
            do something to "$file" > "$somedir/$newfile"
          done
          

          【讨论】:

            【解决方案6】:
            OUTPUT="$(pwd)";
            for file in `find . -iname "*.pdf"`;
            do
              echo $file;
              cp $file $file.xml
              echo "file created in directory = {$OUTPUT}"
            done
            

            这将创建一个名为 whatyourfilename.xml 的新文件,对于 hello.pdf,创建的新文件将是 hello.pdf.xml,基本上它会创建一个在末尾附加 .xml 的新文件。

            请记住,上面的脚本在目录/home/devel/stuff/static/ 中查找文件名与查找命令的匹配器字符串匹配的文件(在本例中为 *.pdf),并将其复制到您当前的工作目录。

            此特定脚本中的 find 命令仅查找文件名以 .pdf 结尾的文件 如果您想为文件名以 .txt 结尾的文件运行此脚本,则需要将 find 命令更改为 find /home/devel/stuff/static/ -iname "*.txt"

            【讨论】:

              【解决方案7】:

              曾经我想从我的文件中删除尾随 -min。即希望alg-min.jpg 变成alg.jpg。所以经过一番挣扎,设法弄清楚了这样的事情:

              for f in *; do echo $f; mv $f $(echo $f | sed 's/-min//g');done;
              

              希望这对愿意删除SUBTITUDE他们文件名的某些部分的人有所帮助。

              【讨论】:

                猜你喜欢
                • 2014-09-09
                • 1970-01-01
                • 1970-01-01
                • 2014-06-08
                • 2021-05-26
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多