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 {} \;
しかし、出力を1行にまとめて印刷する方法がわかりません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 {} \;
空のファイルとスペースを含むファイル名も処理されます。basename
MacOSユーザーは使用できない可能性があります。
答え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/\([^/]*/\)*||'