ディレクトリに多数のテキストファイルがあり、ディレクトリ内のすべてのファイルの最後の行を削除したい。
どうすればできますか?
vim
にアクセスできる場合は、以下を使用できます。
for file in ./*
do
if [ -f "${file}" ]
then
vim -c '$d' -c "wq" "${file}"
fi
done
GNU sed
がある場合は、この素敵なワンライナーを使用できます。
sed -i '$ d' ./*
現在のディレクトリにある非表示ではない各ファイルの最後の行を削除します。スイッチ-i
for GNU sed
は所定の位置で動作することを意味し、'$ d'
はsed
に最後の行($
は最後を意味し、d
は削除を意味します)。
ディレクトリに通常のファイル以外のものが含まれている場合、またはファイル名にスペース/改行が含まれているファイルがある場合、他のすべての回答に問題があります。関係なく機能するものは次のとおりです。
find "$dir" -type f -exec sed -i '$d' '{}' '+'
find "$dir" -type f
:$dir
ディレクトリでファイルを検索します-type f
これは通常のファイルです。-exec
見つかった各ファイルに対してコマンドを実行しますsed -i
:ファイルを編集します。'$d'
:最後の($
)行を(d
)削除します。'+'
:sed
に引数を追加し続けるようにfindに指示します(@zwolのおかげで、ファイルごとにコマンドを個別に実行するよりも少し効率的です)。サブディレクトリに降りたくない場合は、引数-maxdepth 1
をfind
に追加できます。
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
ファイルが比較的小さい場合は、ファイルごとにいくつかのコマンドを実行するため、効率が低下する可能性があります。
最後の改行文字の後(最後の行の後)に余分なバイトが含まれているファイルの場合、つまり、区切りのない最後のlineがある場合、tail
実装、tail -n 1
は、これらの余分なバイト(GNU tail
など)、または最後の(適切に区切られた)行とそれらの余分なバイトのみを返します。
よりポータブルなアプローチ:
for f in ./*
do
test -f "$f" && ed -s "$f" <<\IN
d
w
q
IN
done
d
はデフォルトで最後の行を選択するため、この場合はed
が$d
と同じであることを除いて、これには説明は必要ないと思います。
これは再帰的に検索せず、隠しファイル(別名dotfiles)を処理しません。
これらも編集したい場合は、 ディレクトリ内の隠しファイルと*を照合する方法をご覧ください
ドットファイルを含む、現在のディレクトリから再帰的に始まるすべてのファイル用の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 {} +
こちらもご覧ください: