Linux:管道`查找`文本文件列表| `dos2unix` | `dd`命令

时间:2015-06-09 09:28:27

标签: bash pipe ubuntu-14.04

我正在尝试做什么:

  • 第1行:找到任何.txt或.TXT文件并将它们传输到下一个命令
  • 第2行:将.txt文件转换为unix格式(摆脱Windows行结尾)
  • 第3行:删除文件的最后一行,该行始终为空白
  
find "${TEMPDIR}" -name *.[Tt][Xx][Tt] | /
xargs dos2unix -k | /
dd if=/dev/null of="$_" bs=1 seek=$(echo $(stat --format=%s "$_" ) - $( tail -n1 "$_" | wc -c) | bc )

我无法将xargs dos2unix -k | /的(编辑 输出)文件名传输到第三行,我收到以下错误:

stat: cannot stat '': No such file or directory
tail: cannot open '' for reading: No such file or directory
dd: failed to open '': No such file or directory

显然,我错误地认为"$_"足以通过管道传递输出。

如何将xargs dos2unix -k的输出(文本文件)传输到第三行dd if=/dev/null of="$_" bs=1 seek=$(echo $(stat --format=%s "$_" ) - $( tail -n1 "$_" | wc -c) | bc )

第3行的解决方案来自另一个关于从文件中删除最后一行的问题的答案,特别是这个答案被吹捧为大文件的一个很好的解决方案:https://stackoverflow.com/a/17794626/893766

3 个答案:

答案 0 :(得分:5)

这有帮助吗?

find "${TEMPDIR}" -iname '*.txt' -exec dos2unix "{}" \; -exec sed -i '$d' "{}" \;

答案 1 :(得分:2)

您可以尝试将dos2unix替换为显式替换:

find "${TEMPDIR}" -iname '*.txt' -exec cat {} \; |
tr -d '\r' |
...

由于新行的窗口为\r\n,您可以使用\r命令删除tr的所有匹配项。

关于find命令,您可以使用选项-iname进行不区分大小写的搜索,使用-exec运行命令。

答案 2 :(得分:1)

如果文件非常大,那么您已经通过使用tr重写文件来提高效率。然后,您正在使用tail第二次阅读它,以获取最后一行的索引。

我能想到的最低效的解决方法是用一个执行两个函数的命令替换dos2unixdd,因此您只需读取和写入一次输出文件。

find "$TMPDIR" -iname '*.txt' -exec perl -i -ne '
    print $line if defined $line; ($line = $_) =~ s/\015$//' {} \;

您尝试将$_用于当前文件名并不起作用。 $_的值是前一个已完成命令使用的最后一个文件名;但是在管道中间,还没有完成任何事情。一种可能的解决方法(我只是为了说明而不是推荐的解决方案)将运行xargs中您可以访问{}的所有内容,类似于find -exec中的工作方式

find "$TMPDIR" -iname '*.txt' -print0 |
xargs -r0 sh -c 'dos2unix -k "{}"
    if=/dev/null of="{}" bs=1 seek=$(
        echo $(stat --format=%s "{}" ) - $( tail -n1 "{}" | wc -c) | bc)

我添加了-print0和相应的xargs -0以及xargs -r作为良好形式的插图;虽然零终止文本格式是GNU find扩展名,但通常在其他平台上找不到。

(私下,我可能也会用简单的Awk脚本替换seek计算,而不是在执行减法时花费三个进程。)