读取包含子文件夹的文件夹中所有txt文件的第一行,并将文件名和第一行打印到另一个文件

读取包含子文件夹的文件夹中所有txt文件的第一行,并将文件名和第一行打印到另一个文件

我需要在 Ubuntu 机器上读取大约 20,000 个 txt 文件,并将每个文件的第一行插入到新的 txt 文件中,如下所示:

Filename1.txt | FirstLineoftheFilename1.txt
Filename2.txt | FirstLineoftheFilename2.txt
Filename3.txt | FirstLineoftheFilename3.txt

我尝试了sed命令,我可以打印第一行。

以下find命令将识别正确的文件:

find /db/users/logs/ -name '*.txt' -exec sed -n '1p' {} \; -exec basename {} \;

但我不知道如何在一行上组合find和打印输出。sed

有什么帮助吗?

提前致谢!

答案1

你可以使用 GNU awk

LC_ALL=C find /db/users/logs/ -name '*.txt' -type f -exec gawk '{
  f = FILENAME; sub(".*/", "", f)
  print f" | "$0; nextfile}' {} +

或者perl

LC_ALL=C find . -type f -name '*.txt' -exec perl -lne '
  print $ARGV =~ s:.*/::r . " | $_"; close ARGV' {} +

或者外壳:

LC_ALL=C find /db/users/logs/ -type f -name '*.txt' -exec sh -c '
  for file do
    <"$file" IFS= read -r line || [ -n "$line" ] &&
      printf "%s\n"  "${file##*/} | $line"
  done' sh {} +

sh(如果第一行包含 NUL 字符,则该方法将无法在大多数实现中正常工作;尽管对于文本文件)。

答案2

还有另一种变体:

$ find /db/users/logs/ -type f -name "*.txt" -exec \
  sh -c 'printf "%s | %s\n" "$(basename $1)" "$(head -1 $1)"' shellproc {} \;

还将处理空文件和带有空格的文件名。 MacOS 用户可能无法basename使用。

答案3

方法-a)

find /db/users/logs -type f -name '*.txt' \
    ! -empty -printf '%f | ' \
    -exec head -n 1 \{\} \;

find方法ii)我们使用perl模块File::Find封装了命令的功能

perl -MFile::Find -e '
  find( sub { my $fh;
     -f && ! -z && /\.txt$/ and 
     open($fh, "<", $_) and 
     print("$_ | " . <$fh>) },
   shift )
' /db/users/logs

感谢 Stephane 指出需要基本名称。如果文件名中没有换行符,您也可以执行此操作,并且我们可以使用冒号作为分隔符而不是管道。

$ find /db/users/logs/  \
    -type f -name '*.txt' \
    -exec grep -Hm1 "^" {} + |
  sed 's|^/db/users/logs/\([^/]*/\)*||' 

相关内容