回答:
GNUをお持ちの場合、この素敵なonelinerを使用できますsed
。
sed -i '$ d' ./*
現在のディレクトリにある隠されていない各ファイルの最後の行を削除します。-i
GNU用のスイッチはsed
、所定の場所で動作することを意味し、最後の行を削除するように'$ d'
指示しますsed
($
最後をd
意味し、削除を意味します)。
-i
これは議論の余地があるので、GNUismであるが、私はいくつかの古いバージョンがあることを指摘して失敗した場合、私は私の古い髭が立っ失うことになるsed
あなたは間の空白を置くことを許可していない$
とd
(または、一般に、パターンとコマンドの間)。
*(.)
では、通常のファイルのグロブに使用できますが、他のシェルについては知りません。
ディレクトリに通常のファイル、またはファイル名にスペース/改行が含まれるファイル以外のものが含まれている場合、他の回答にはすべて問題があります。関係なく動作するものを次に示します。
find "$dir" -type f -exec sed -i '$d' '{}' '+'
find "$dir" -type f
:ディレクトリ内のファイルを見つける $dir
-type f
これは通常のファイルです。-exec
見つかった各ファイルでコマンドを実行しますsed -i
:ファイルを適切に編集します。'$d'
:d
最後の($
)行を削除()します。'+'
:findに引数を追加し続けるように指示しますsed
(@zwolのおかげで、各ファイルに対してコマンドを個別に実行するよりも少し効率的です)。サブディレクトリに降りたくない場合は、引数-maxdepth 1
をに追加できますfind
。
find
これの現在のバージョンではより効率的に記述されていfind $dir -type f -exec sed -i '$d' '{}' '+'
ます。)
-print0
完全なコマンドに存在しないのに、なぜそれを説明に入れるのですか?
-depth 0
機能しません(findutils 4.4.2)-maxdepth 1
。代わりにが必要です。
-exec
。
GNUを使用sed -i '$d'
すると、ファイル全体を読み取り、最終行なしでコピーを作成することを意味しますが、(少なくとも大きなファイルの場合)ファイルを所定の位置に切り捨てる方がはるかに効率的です。
GNU truncate
では、次のことができます。
for file in ./*; do
[ -f "$file" ] &&
length=$(tail -n 1 "$file" | wc -c) &&
[ "$length" -gt 0 ] &&
truncate -s "-$length" "$file"
done
ファイルが比較的小さい場合、ファイルごとに複数のコマンドを実行するため、おそらく効率は低下します。
最後の改行文字の後(最後の行の後)に余分なバイトを含むファイル、または区切りのない最後の行がある場合、tail
実装に応じて、tail -n 1
それらの余分なバイトのみを返します(GNUなどtail
)または最後の(適切に区切られた)行とそれらの余分なバイト。
|wc -c
中に必要tail
ですか?(またはa ${#length}
)
${#length}
バイトで$(...)
はなく文字をカウントし、末尾の改行文字を削除するため、機能しません${#...}
すべての文字がシングルバイトであっても1つずれます。
よりポータブルなアプローチ:
for f in ./*
do
test -f "$f" && ed -s "$f" <<\IN
d
w
q
IN
done
私はこれに説明が必要だとは思わない...多分この場合d
は同じであることを除いて$d
ので、ed
デフォルトは最後の行を選択することによって。
これは再帰的に検索せず、隠しファイル(別名ドットファイル)を処理しません。
これらも編集する場合は、ディレクトリ内の隠しファイルと*を一致させる方法を参照してください。
[[]]
する[]
と、完全にPOSIX準拠になります。([[ ... ]]
バシズムです。)
[[
バシズムではありませんが)
ドットファイルを含む現在のディレクトリで再帰的に開始するすべてのファイル用のPOSIX準拠のワンライナー:
find . -type f -exec sh -c 'for f; do printf "\$d\nx\n" | ex "$f"; done' sh {} +
以下のため.txt
のファイルのみ、非再帰的に:
find . -path '*/*/*' -prune -o -type f -name '*.txt' -exec sh -c 'for f; do printf "\$d\nx\n" | ex "$f"; done' sh {} +
参照: