【问题标题】:Delete first line of all files in a folder (on ubuntu)删除文件夹中所有文件的第一行(在 ubuntu 上)
【发布时间】:2015-08-27 08:31:47
【问题描述】:

我有一个包含 2800 个 .txt 文件的文件夹,我需要删除每个文件的第一行。除了以 .txt 结尾的事实之外,文件的名称都不同。

是否可以在保持相同文件名的同时做到这一点(而不是将输出(没有第一行的文件)发送到另一个文件)...

【问题讨论】:

  • find /path -name *.txt -exec sed -i '1d' '{}'\; 应该做的事情。 (之前尝试在测试目录中的文件子集)

标签: ubuntu awk sed terminal bioinformatics


【解决方案1】:

对于少数文件,我会写的是

for f in *.txt; do sed 1d "$f" >tmpfile; mv tmpfile "$f"; done

但是,对于足够多的文件,这是行不通的,因为 shell 会将 *.txt 扩展为一个太长的参数列表。

在那种情况下(听起来像你的情况),更好的方法是

ls | grep '.txt$' | while read f; do sed 1d "$f" >tmpfile; mv tmpfile "$f"; done

但是,您应该知道,这存在原则上的问题(正如@EdMorton 在 cmets 中在此答案的早期版本中所强调的那样)。一个是如果你不幸拥有一个名称以.txt 结尾的目录,这将有麻烦(如果你真的觉得需要,你可以用test -f 处理)。另一个是如果其中一个文件名中有一些奇怪的字符(例如\n,或者一种或其他类型的引号),read 可能会出现问题。您可以通过摆弄IFS(参见 cmets)来处理此类事情,但最好快速浏览一下您正在处理的文件,并先修复这些错误的文件名。

你不应该做的是ls *.txt | ...,因为如果文件数量足够长以至于for f in *.txt; do ... 不起作用,那么ls *.txt 也不起作用。


你可以做更多复杂的事情。

find . -type f -name \*.txt | while read f; do ...

这会专门选择以.txt 结尾的文件,但我总是发现file 的选项打字或阅读不整齐,感觉ls+grep 在这里更整洁。

另一种可能是

find . -type f -name \*.txt -exec sed -i 1d '{}' \;

这非常健壮,但就像大多数非平凡的file 命令一样,它最终看起来像一团糟,你必须记住find 的非显而易见的语法。另外 除非您的 sed 支持无参数 -i 选项(POSIX sed 没有 -i,并且 OS X 和其他平台上的 sed 没有 sed BSD 实际上需要指定扩展)。此外,此方法仅限于单个命令,因此不适用于需要对文件执行更多操作的情况。

【讨论】:

  • 给定不同的文件名,这将以许多有趣的方式失败。不要这样做。 google解析ls,引用shell变量,不要写shell循环等
  • @EdMorton 是的,当然,它对半病态文件名(在许多情况下包括带有空格的文件名)并不可靠,而且我几乎肯定不会在正在运行的脚本中写这个运行不受监视,但考虑到我可以首先浏览我要处理的文件列表,这就是我认为足够好的。就是说,引用$f 是一种很好的反应,而且不会有点草率,所以我将编辑答案以将其放入。
  • 这是 shell 基础 - 不要解析 ls 的输出,除非您有非常特定的目的并完全理解效果,否则请始终引用您的变量,并始终使用 IFS=-r(例如while IFS= read -r f)再次除非你有一个非常具体的目的并完全理解效果。按照这些基本规则以正确的方式做这件事非常容易,所以为什么要以错误的方式做,然后说“因为已经够好了”。
  • @EdMorton 我意识到ls *.txt 在此类文件太多时会失败(doh!),所以重写了。我只是顺便提到了IFS,因为这是shell 语法奥秘,而不是基础。专业知识是知道什么时候“足够好”足够好,什么时候不够好。
【解决方案2】:

这样的东西可以解决问题

sed -i '1d' *.txt

其中 -i 是就地编辑

编辑:添加

请也试试这个

time sed -i '1d' *.txt

并与其他解决方案进行比较(只是在之前添加时间)[肯定会尝试一些备份文件]

【讨论】:

    【解决方案3】:

    您可以编写一个 bash 脚本。像这样的:

    #!/bin/bash
    for filename in *; 
    do 
        tail -n +2 "${filename}"
    done
    

    从命令行运行它:$ <script_file.sh>

    把这个和一粒盐一起吃。我实际上并没有在 *nix 机器上运行。请参阅here for a variety of ways 删除文件的第一行。另请注意,如果性能对您很重要,tail 应该比 sed 快得多。

    【讨论】:

    • 不客气。您还没有足够的代表投票,但不要忘记接受!
    猜你喜欢
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多