Saya memiliki banyak file teks dalam direktori, dan saya ingin menghapus baris terakhir dari setiap file dalam direktori.
Bagaimana saya bisa melakukannya?
text-processing
files
ThehalfarisedPheonix
sumber
sumber
Jawaban:
Jika Anda memiliki akses ke
vim
, Anda dapat menggunakan:sumber
Anda dapat menggunakan oneliner yang bagus ini jika Anda memiliki GNU
sed
.Ini akan menghapus baris terakhir dari setiap file yang tidak disembunyikan di direktori saat ini. Beralih
-i
untuk GNUsed
berarti beroperasi di tempat dan'$ d'
memerintahkansed
untuk menghapus baris terakhir ($
artinya terakhir dand
berarti menghapus).sumber
-i
yang merupakan GNUism, jadi ini bisa diperdebatkan, tapi saya akan kehilangan janggut lama saya jika saya gagal menunjukkan bahwa beberapa versi yang lebih lamased
tidak memungkinkan Anda untuk meletakkan spasi kosong apa pun di antara$
dand
(atau, secara umum, antara pola dan perintah).*(.)
untuk glob untuk file biasa, saya tidak tahu tentang shell lainnya.Jawaban lain semua memiliki masalah jika direktori berisi sesuatu selain file biasa, atau file dengan spasi / baris baru dalam nama file. Berikut ini sesuatu yang berfungsi:
find "$dir" -type f
: cari file di direktori$dir
-type f
yang merupakan file biasa;-exec
jalankan perintah pada setiap file yang ditemukansed -i
: mengedit file di tempat;'$d'
: delete (d
) baris terakhir ($
).'+'
: memberitahu find untuk terus menambahkan argumensed
(sedikit lebih efisien daripada menjalankan perintah untuk setiap file secara terpisah, terima kasih kepada @zwol).Jika Anda tidak ingin turun ke subdirektori, maka Anda dapat menambahkan argumen
-maxdepth 1
kefind
.sumber
find
ini, ini ditulis dengan lebih efisienfind $dir -type f -exec sed -i '$d' '{}' '+'
.)-print0
tidak hadir dalam perintah penuh, mengapa memasukkannya ke dalam penjelasan?-depth 0
tidak berfungsi (findutils 4.4.2), mestinya sebaliknya-maxdepth 1
.-exec
.Menggunakan GNU
sed -i '$d'
berarti membaca file lengkap dan membuat salinannya tanpa baris terakhir, sementara itu akan jauh lebih efisien untuk hanya memotong file di tempat (setidaknya untuk file besar).Dengan GNU
truncate
, Anda dapat melakukan:Jika file relatif kecil, itu mungkin akan kurang efisien karena menjalankan beberapa perintah per file.
Perhatikan bahwa untuk file yang berisi byte tambahan setelah karakter baris baru terakhir (setelah baris terakhir) atau dengan kata lain jika mereka memiliki baris terakhir yang tidak dibatasi , maka tergantung pada
tail
implementasinya,tail -n 1
akan mengembalikan hanya byte tambahan tersebut (seperti GNUtail
), atau baris terakhir (dibatasi dengan benar) dan byte tambahan itu.sumber
|wc -c
ditail
panggilan? (atau a${#length}
)${#length}
tidak akan berfungsi karena menghitung karakter, bukan byte dan$(...)
akan menghapus karakter baris baru tailing sehingga${#...}
akan dimatikan oleh satu bahkan jika semua karakter single-byte.Pendekatan yang lebih portabel:
Saya tidak berpikir ini perlu penjelasan apa pun ... kecuali mungkin dalam kasus
d
ini sama$d
karenaed
secara default memilih baris terakhir.Ini tidak akan mencari secara rekursif dan tidak akan memproses file tersembunyi (alias dotfiles).
Jika Anda ingin mengeditnya juga lihat Cara mencocokkan * dengan file tersembunyi di dalam direktori
sumber
[[]]
ke[]
maka akan sepenuhnya POSIX compliant. ([[ ... ]]
is a Bashism.)[[
bukan bashism )Satu-liner yang sesuai dengan POSIX untuk semua file secara rekursif dimulai pada direktori saat ini, termasuk dot-file:
Hanya untuk
.txt
file, non-rekursif:Lihat juga:
sumber