Cara elegan untuk mencari file UTF-8 dengan BOM?

94

Untuk tujuan debugging, saya perlu mencari direktori secara rekursif untuk semua file yang dimulai dengan UTF-8 byte order mark (BOM). Solusi saya saat ini adalah skrip shell sederhana:

find -type f |
while read file
do
    if [ "`head -c 3 -- "$file"`" == $'\xef\xbb\xbf' ]
    then
        echo "found BOM in: $file"
    fi
done

Atau, jika Anda lebih suka baris satu yang pendek dan tidak terbaca:

find -type f|while read file;do [ "`head -c3 -- "$file"`" == $'\xef\xbb\xbf' ] && echo "found BOM in: $file";done

Ini tidak berfungsi dengan nama file yang berisi jeda baris, tetapi file seperti itu tidak diharapkan.

Apakah ada solusi yang lebih singkat atau lebih elegan?

Apakah ada editor teks atau makro yang menarik untuk editor teks?

vog
sumber

Jawaban:

166

Bagaimana dengan satu perintah sederhana ini yang tidak hanya menemukan tetapi juga membersihkan BOM yang tidak menyenangkan? :)

find . -type f -exec sed '1s/^\xEF\xBB\xBF//' -i {} \;

Saya suka "temukan" :)

Peringatan Di atas akan mengubah file biner yang berisi ketiga karakter tersebut.

Jika Anda hanya ingin menampilkan file BOM, gunakan yang ini:

grep -rl $'\xEF\xBB\xBF' .
Denis
sumber
9
Salah mendeteksi PDF dengan penanda BOM .. itu karena ia mencari seluruh dokumen, bukan hanya baris pertama
Olivier Refalo
1
Atau dengan ack: "ack '\ xEF \ xBB \ xBF'"
Smar
5
ubah perintah sed untuk menambahkan 1 sebelum awalan 's sehingga hanya berlaku untuk baris pertama
Ben Combee
27
Gunakan grep -rlI $'\xEF\xBB\xBF' .untuk mengabaikan file biner.
dbernard
1
Mendeteksi dan memodifikasi JPG dan file biner lainnya, seperti yang telah dikatakan.
Jehy
41

Cara terbaik dan termudah untuk melakukannya di Windows:

Total Commander → buka direktori root proyek → temukan file ( Alt+ F7) → jenis file *. * → Temukan teks "EF BB BF" → centang 'Hex' checkbox → cari

Dan Anda mendapatkan daftarnya :)

Jan Przybylo
sumber
4
Bagus, terutama penggunaan Total commander favorit saya yang sudah lama, tapi sayangnya ini mengalami masalah yang sama seperti banyak lainnya: ia mencari semua byte dalam satu fle, begitu banyak gambar dll dilaporkan. Ini dapat sedikit diperbaiki dengan menggunakan RegEx daripada Hex dan mencari "^ \ xEF \ xBB \ xBF" yang akan menghilangkan banyak gambar tetapi masih memiliki file yang memiliki BOM di tengah-tengah file (walaupun harus ada sedikit) dan tentu saja file biner apa pun yang kebetulan memiliki kode karakter baris baru ascii sebelum BOM. Tetap saja, semua gambar hilang dalam pencarian percobaan saya.
Legolas
13
find . -type f -print0 | xargs -0r awk '
    /^\xEF\xBB\xBF/ {print FILENAME}
    {nextfile}'

Sebagian besar solusi yang diberikan di atas menguji lebih dari baris pertama file, bahkan jika beberapa (seperti solusi Marcus) kemudian memfilter hasilnya. Solusi ini hanya menguji baris pertama dari setiap file sehingga seharusnya lebih cepat.

Aron Griffis
sumber
1
Got bekerja dengan berikut ini di Linux (RHEL6) -find . -type f -print0 | xargs -0 awk '/^\xEF\xBB\xBF/ {print FILENAME} {nextfile}'
Olivier Refalo
Bagaimana saya harus mengubah kode Anda untuk memperbaiki file-file ini setelah mereka ditemukan?
Black
7

Jika Anda menerima beberapa positif palsu (jika ada file non-teks, atau dalam kasus yang tidak biasa ada ZWNBSP di tengah file), Anda dapat menggunakan grep:

fgrep -rl `echo -ne '\xef\xbb\xbf'` .
CesarB
sumber
5

Saya akan menggunakan sesuatu seperti:

grep -orHbm1 "^`echo -ne '\xef\xbb\xbf'`" . | sed '/:0:/!d;s/:0:.*//'

Yang akan memastikan bahwa BOM terjadi mulai dari byte pertama file.

Marcus Griep
sumber
5

Anda dapat menggunakan grepuntuk menemukannya dan Perl untuk menghapusnya seperti ini:

grep -rl $'\xEF\xBB\xBF' . | xargs perl -i -pe 's{\xEF\xBB\xBF}{}'
teori
sumber
Yang ini berhasil untuk saya, jawaban yang diterima tidak (Saya menggunakan Mac)
mjsarfatti
4

Untuk pengguna Windows, lihat ini (skrip PHP yang baik untuk menemukan BOMdalam proyek Anda).

julien
sumber
Situs web yang ditautkan menunjukkan: "Situs Web Offline, Tidak Tersedia Versi Cache".
vog
skrip yang sama juga tersedia di github: github.com/emrahgunduz/BomCleaner
emrahgunduz
Terima kasih sobat, Jawaban Anda menyelamatkan hari saya.
Krunal Panchal
Dan BOM Finder: github.com/svn2github/wikia/blob/master/extensions/FCKeditor/… (jika seseorang tidak menyukai pembersihan 'otomatis', atau hanya ingin mencari file dengan BOM)
meloniq
3

Solusi berlebihan untuk ini adalah phptags(bukan vialat dengan nama yang sama), yang secara khusus mencari skrip PHP:

phptags --warn ./

Akan menghasilkan sesuatu seperti:

./invalid.php: TRAILING whitespace ("?>\n")
./invalid.php: UTF-8 BOM alone ("\xEF\xBB\xBF")

Dan --whitespacemode tersebut akan secara otomatis memperbaiki masalah tersebut (secara rekursif, tetapi menegaskan bahwa itu hanya menulis ulang skrip .php.)

mario
sumber
2
find -type f -print0 | xargs -0 grep -l `printf '^\xef\xbb\xbf'` | sed 's/^/found BOM in: /'
  • find -print0 menempatkan null \ 0 di antara setiap nama file daripada menggunakan baris baru
  • xargs -0 mengharapkan argumen yang dipisahkan nol, bukan dipisahkan baris
  • grep -l mencantumkan file yang cocok dengan ekspresi reguler
  • Regex ^\xeff\xbb\xbftidak sepenuhnya benar, karena akan cocok dengan file UTF-8 non-BOM jika memiliki spasi lebar nol di awal baris
Jonathan Wright
sumber
Anda masih membutuhkan "kepala 1" di pipa sebelum grep
MSalters
2

Saya menggunakan ini untuk memperbaiki hanya file JavaScript:

find . -iname *.js -type f -exec sed 's/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;
Refineo
sumber
0

Jika Anda mencari file UTF, perintah file berfungsi. Ini akan memberi tahu Anda apa pengkodean file itu. Jika ada karakter non ASCII di sana, itu akan muncul dengan UTF.

file *.php | grep UTF

Itu tidak akan bekerja secara rekursif. Anda mungkin dapat memasang beberapa perintah mewah untuk membuatnya rekursif, tetapi saya hanya mencari setiap level secara individual seperti berikut, sampai saya kehabisan level.

file */*.php | grep UTF
Mike Dotterer
sumber