【问题标题】:Need to change file content with script but retain original filenames需要使用脚本更改文件内容但保留原始文件名
【发布时间】:2012-11-17 14:35:16
【问题描述】:

我在一个文件夹中有数千个包含编码天气信息的文件。我需要为每个文件添加带有控制字符的页眉和页脚。这不是问题,因为我在单独的文件中有页眉和页脚(通过 bash 脚本中的 cat 命令实现)。

但是,修改后的文件需要保留其原始名称 - 这给我带来了一个问题,因为我只有非常基本的脚本知识。保留它们的原因是这些文件将被解析和解码。文件名包含解码器如何处理内容的重要信息。

所有要解码的文件都在一个单独的文件中,list_of_files_to_decode.txt

文件夹内容的一部分可能如下所示:

a_snvs02wiix170600_c_eswi_20121117062131_76.txt
a_smci40babj170600_c_kwbc_20121117061545_3.txt
a_sath40vtbb170600_c_ekmi_20121117061604_95.txt
a_usxx40mynn70600cca_c_edzw_20121117062020_34.txt
a_siin40dems170600_c_ojam_20121117062020_40.txt
a_smxx40fapr170600rra_c_lowm_20121117062604_67.txt    
list_of_files_to_decode.txt   
start-seq.txt    
stop-seq.txt  

我已经检查了网络,并测试了我自己的一些想法 - 使用 awksed - 但我真的找不到任何合适的方法来轻松实现这一目标。因此,我将不胜感激有关如何继续的帮助或提示。

【问题讨论】:

    标签: bash sed awk filenames


    【解决方案1】:
    while IFS= read -r file; do
        cat header.txt "$file" footer.txt > newfile && mv newfile "$file"
    done < list_of_files_to_decode.txt
    

    解释

    • 我只是使用串联和 shell 重定向
    • &amp;&amp; 是一个快捷方式。这与if condition; then action; fi 相同

    【讨论】:

    • +1 相应添加;-)
    • 对于带有反斜杠的文件名和以空格开头或结尾的文件名会失败,并且可能存在其他不寻常的情况。始终将您的 while 读取循环写为 while IFS= read -r variable 而不仅仅是 while read variable。 IFS= 处理以空格开头或结尾的文件名,而 -r 处理包含反斜杠的文件名。包含换行符的文件名仍然会失败,但有一点....
    • 当你控制输入文件和内容时,它不是必需的,但是为了更通用的可重复使用的 sn-p 进行相应的后期编辑。
    【解决方案2】:

    唯一安全的方法是先重命名原始文件

    mv $file $file.orig
    cat header $file.orig footer > $file && rm $file.orig
    

    反之亦然创建一个新文件,然后覆盖原来的文件

    cat header $file footer > $file.new && mv -f $file.new $file
    

    【讨论】:

    • 这比我预想的还要简单。我已经测试过了,它工作正常。非常感谢。
    • 总是引用你的变量,除非你有一个很好的、明确的理由不这样做。 mv $file $file.origmv "$file" "${file}.orig" 非常不同,几乎可以肯定不是你想要的。
    【解决方案3】:

    sed 的无环方式:

    OLDIFS=$IFS; IFS=$'\n'
    sed -i '1 r header.txt
            1 N
            $ r footer.txt' $(<list_of_files_to_decode.txt)
    IFS=$OLDIFS
    


    笔记:
    • 仅在文件名中有空格的情况下将IFS 设置为换行符
    • r 在读取下一行时打印文件内容
    • 1 N 防止在header.txt 的内容之前打印第一行

      (详情:它读取第 2 行并追加到模式空间,触发r 打印出header.txt 的内容。之后,现在由第 1 行和第 2 行组成的模式空间仅在循环结束)

    • 当然,如果您使用脚本,则可能不需要备份和重置IFS

    【讨论】:

    • 总是引用你的变量,除非你有一个很好的、明确的理由不这样做。 IFS=$OLDIFS 与 IFS="$OLDIFS" 非常不同,几乎可以肯定不是您想要的。
    • 除非涉及命令替换,否则不会在分配时发生分词。
    • 您需要担心的不仅仅是分词(请参阅gnu.org/software/bash/manual/bashref.html#Shell-Expansions),但看起来您是正确的,并且在赋值中不引用变量是安全的。以前从未注意到这一点,因为我总是引用我的变量,除非我有非常具体的理由不这样做。避免在其他时候感到惊讶。
    猜你喜欢
    • 2020-02-16
    • 2015-06-09
    • 2016-03-05
    • 2016-05-27
    • 2018-02-04
    • 2020-06-20
    • 2022-01-01
    • 2018-05-08
    • 1970-01-01
    相关资源
    最近更新 更多