grep mulai dari file?


10

Dalam shell linux, saya ingin memastikan bahwa set file tertentu semua dimulai dengan <?, memiliki string yang tepat dan tidak ada karakter lain di awal. Bagaimana saya bisa grep atau menggunakan yang lain untuk mengekspresikan "file diawali dengan"?


Sunting: Saya wildcarding ini, dan headtidak memberikan nama file pada baris yang sama, jadi ketika saya ambil itu, saya tidak melihat nama file. Juga, "^<?"sepertinya tidak memberikan hasil yang benar; pada dasarnya saya mendapatkan ini:

$> head -1 * | grep "^<?"
<?
<?
<?
<?
<?
...

Semua file sebenarnya bagus.

Jawaban:


11

Di Bash:

for file in *; do [[ "$(head -1 "$file")" =~ ^\<\? ]] || echo "$file"; done

Pastikan itu adalah file:

for file in *; do [ -f "$file" ] || continue; [[ "$(head -1 "$file")" =~ ^\<\? ]] || echo "$file"; done


dan karena kita semua sangat luar biasa: jangan gunakan operator glob pada sejumlah besar nama file, alih-alih gunakanfind
akira

menggunakan findjuga dapat mengembalikan hanya file biasa secara langsung untuk memulai pipa.
mpez0

1
Anda benar-benar dapat melakukannya di Bash saat menggunakan readalih-alih headjuga: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen

4

Lakukan grep:

$ head -n 1 * | grep -B1 "^<?"
==> foo <==
<?
--
==> bar <==
<?
--
==> baz <==
<?

Singkirkan nama file:

$ head -n 1 * | grep -B1 "^<?" | sed -n 's/^==> \(.*\) <==$/\1/p'
foo
bar
baz

3

Anda dapat menggunakan awk untuk ini:

$ cat test1
<?xxx>
111
222
333
$ cat test2
qqq
aaa
zzz
$ awk '/^<\?/{print "Starting with \"<?\":\t" ARGV[ARGIND]; nextfile} {print "Not starting with \"<?\":\t" ARGV[ARGIND]; nextfile}' *
Starting with "<?":     test1
Not starting with "<?": test2
$

3

Kecuali untuk file kosong, skrip Perl ini tampaknya berfungsi:

perl -e 'while (<>) { print "$ARGV\n" unless m/^<\?/; close ARGV; }' *

Saya tidak segera yakin bagaimana menangani file kosong; Saya akan tergoda untuk memperlakukan mereka sebagai kasus khusus yang terpisah:

find . -type f -size +0 -print0 |
    xargs -0 perl -e 'while (<>) { print "$ARGV\n" unless m/^<\?/; close ARGV; }'

2

Coba ini

for i in `find * | grep "php$"`; do echo -n $i " -> "; head -1 $i; done

Ini akan mendapatkan daftar setiap file yang diakhiri dengan PHP, lalu loop melalui itu. menggemakan nama file dan kemudian mencetak baris pertama file. Saya baru saja memasukkan

akan memberi Anda output seperti:

calendar.php  -> <?php
error.php  -> <?php
events.php  -> <?php
gallery.php  ->
index.php  -> <?php
splash.php  -> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
information.php  -> <?php
location.php  -> <?php
menu.php  -> <?php
res.php  -> <?php
blah.php  -> <?php

maka Anda dapat menempelkan grep normal di akhir untuk menyingkirkan apa yang ingin Anda lihat dan menemukan pengecualian saja

for i in `find * | grep "php$"`; do echo -n $i " -> "; head -1 $i; done | grep -v "<?php"

keluaran:

gallery.php  ->
splash.php  -> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

4
Penggunaan grep yang tidak berguna; gunakan "find -name '* .php'". Juga, penggunaan variabel yang berbahaya: gunakan "find -exec your command here '{}' '+'" untuk menghindari masalah dengan nama file "khusus". Selain itu, selalu kutip variabel Anda: "head -1" $ i "", bukan "head -1 $ i".
janmoesen

for x in *.php;do echo $x \"kepala -n1 $ x\";done
user23307

1

Bash 4.0

#!/bin/bash
shopt -s globstar
for php file in /path/**/*.php
do
   exec 4<"$php";read line <&4;exec 4<&-
   case "$line" in
     "<?"*) echo "found: $php"
   esac

done

0
cat file.txt | head -1 | grep "^<?"

harus melakukan apa yang Anda minta.


Ya, tetapi jika saya wildcard, itu tidak memberi saya nama file :( Juga "^ <?" Tidak bekerja untuk saya, saya menggunakan -v switch.
user13743

2
@Phoshi catPenggunaan kompulsif , head -1 file.txt | grep "^<?"sudah cukup.
Benjamin Bannier

1
Penggunaan kucing yang tidak berguna: - (((
vwegert

Kucing tidak berguna tidak berguna :(
user13743

Saya merasa jauh lebih mudah untuk mengingat perintah jika Anda menjaga semuanya modular dan rusak. Saya tahu kucing akan bekerja, saya tidak tahu apakah commandakan mengambil file sebagai argumen. Mungkin tidak sepenuhnya diperlukan, tapi saya tidak akan mengeluarkannya :)
Phoshi

0

ini:

  % for i in *; do head -1 $i | grep "^<?" ; echo "$i : $?"; done

memberi Anda sesuatu seperti ini:

  foo.xml: 0
  bla.txt: 1

setiap file yang tidak mengandung pola Anda akan "ditandai" dengan "1". Anda dapat bermain dengan itu sampai sesuai dengan kebutuhan Anda.


1
Anda perlu mengutip nama file jika dapat mengandung spasi. Dan Anda mungkin ingin kehilangan output dari 'grep' ke / dev / null. Anda juga dapat menggunakan: head -1 "$i" | grep '^<?' || echo "$i"yang hanya akan mencetak nama file jika bermasalah.
Jonathan Leffler

2
Itulah gunanya "grep -q". :-)
janmoesen

0

Biarkan aku mencoba ini

temukan -type f | awk '
{
 if (getline ret <$ 0) {
  if (ret ~ "^ <\\? $") {
   cetak "Bagus [" $ 0 "] [" ret "]";
  }lain{
   cetak "Gagal [" $ 0 "]";
  };
 }lain{
  cetak "kosong [" $ 0 "]";
 };
 tutup ($ 0);
} '

tidak ada yang mengatakan wak tidak tersedia :-)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.