【问题标题】:Insert characters into a filename在文件名中插入字符
【发布时间】:2013-01-30 19:16:55
【问题描述】:

我有一个目录,其中包含一堆标题为(例如)的文件

how it is:            how it should be:
945TITLE-1.txt        945TITLE-00.txt
945TITLE-10.txt       945TITLE-01.txt
945TITLE-2.txt        945TITLE-02.txt
945TITLE-23.txt       945TITLE-03.txt
945TITLE-3.txt        945TITLE-10.txt
945TITLE.txt          945TITLE-23.txt

破折号后面的数字和文本可以改变,所以它需要是可变的。 忽略未编号的文件(本例中为 945TITLE.txt) 我正在使用以下行来获取所有以破折号和一位数字结尾的文件

file=`ls -1 working/pages/files | grep [-][0-9].txt`

但现在我不知道如何在破折号和数字之间拼接 0。

for file in $filelist
do  
????
done

经过几次尝试,我得到了最远的结果:

for file in working/pages/files/$filelist
do  
f1=${filelist%%[-]*}
f2=${filelist##*[-]}
finalName=${f1}-0${f2}
echo $finalName
mv $file working/pages/files/$finalName
done

$finalName 的输出每次都是945TITLE-03.txt,它只将mv 命令应用于945TITLE-1.txt(错误地将其更改为945TITLE-03.txt)并说它找不到其他文件(因为它只查看working/pages/files/ 文件夹中的第一个文件)

任何帮助都将不胜感激,我绝不会接受这个解决方案,所以如果你能想到一个更优雅的解决方案,但与我的提议不同,我会很高兴听到它。谢谢

【问题讨论】:

  • 文件夹结构不清楚:所有文件都在一个文件夹中还是在单独的文件夹中?
  • 在设置f1f2 时,您的意思是使用file 而不是filelist
  • 是的,这个例子的 xhtml 应该是 txt。 $filelist 是目录中所有文件的列表 $file 应该是该列表中的一个元素

标签: regex unix grep


【解决方案1】:

这是我在这里制作的一个简单示例,基于您的开始。有一些有趣的特殊外壳可以处理您的945TITLE.txt 案例:

#!/bin/bash

for file in 945*
do
    suffix=${file##*[.]}
    base=$(basename ${file} .${suffix})
    prefix=${base%%[-]*}
    number=${base##*[-]}
    case ${number} in
        ''|*[!0-9]*) number=0 ;;
    esac
    echo ${prefix}-$(printf "%02d" ${number}).${suffix}
done

【讨论】:

  • 问题是,我不知道这些文件将被命名。所以也许?对于 working/pages/files/*.txt 中的文件
  • @ironintention,这也可以。我只是想举一个简单的例子。
【解决方案2】:

想法:

  1. 逐行处理(例如 945TITLE-1.txt)
  2. 首先用“-”分割(给出“945TITLE”和“1.txt”,)
  3. 然后将第一个拆分的第二个输出拆分为“。” (给出“1”和“txt”)

    ls -1 | awk '{ 
             n=split($0, array , "-");
             if( n > 1 ) {
               printf("%s-",array[1]);
               split(array[2],arraydot,".");
               printf("%02d.%s\n", arraydot[1], arraydot[2]);
              } else {
               split(array[1],arraydot, "."); 
               printf("%s-00.%s\n",arraydot[1],arraydot[2]);
             }
          }' | sort
    

    上面的其他条件处理945TITLE.txt的情况

【讨论】:

    【解决方案3】:

    这个 awk-onliner 可以工作:(你可以先去掉结尾的 |sh 来检查生成的 mv 命令。)

    ls -[your options] |awk  -F'-|\\.' 'NF<3{x=$0;sub(/\./,"-00.",x)}NF>2{x=sprintf ("%s-%02d.%s",$1,$2,$3)}{print "mv "$0" "x}' |sh
    

    我用文本文件模拟它。

    kent$  cat test.txt
    945TITLE-1.txt
    945TITLE-10.txt
    945TITLE-2.txt
    945TITLE-23.txt
    945TITLE-3.txt
    945TITLE.txt
    
    kent$  awk  -F'-|\\.' 'NF<3{x=$0;sub(/\./,"-00.",x)}NF>2{x=sprintf ("%s-%02d.%s",$1,$2,$3)}{print "mv "$0" "x}' test.txt
    mv 945TITLE-1.txt 945TITLE-01.txt
    mv 945TITLE-10.txt 945TITLE-10.txt
    mv 945TITLE-2.txt 945TITLE-02.txt
    mv 945TITLE-23.txt 945TITLE-23.txt
    mv 945TITLE-3.txt 945TITLE-03.txt
    mv 945TITLE.txt 945TITLE-00.txt
    

    如果你将结果通过管道传递给 sh,比如awk.....|sh,那些 mv 命令就会被执行。

    【讨论】:

      【解决方案4】:

      这是一个适合您的 Perl 示例:

      perl -E 'while(<*.txt>){ $a = $_; s/-\K\d\./0$&/ || s/\D\K\./-00./; rename $a, $_; }'
      

      未经测试。 ;-)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-26
        • 2013-01-15
        相关资源
        最近更新 更多