grep inizio del file?


10

In una shell Linux, voglio assicurarmi che inizi un certo set di file <?, che abbia quella stringa esatta e nessun altro carattere all'inizio. Come posso grep o usare qualche altro per esprimere "il file inizia con"?


Modifica: sto jolly questo, e headnon dà un nome di file sulla stessa riga, quindi quando lo grep, non vedo il nome del file. Inoltre, "^<?"non sembra dare i risultati giusti; fondamentalmente sto ottenendo questo:

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

Tutti i file sono effettivamente buoni.

Risposte:


11

In Bash:

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

Assicurati che siano file:

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


e dato che siamo tutti così pedanti: non usare l'operatore glob su enormi quantità di nomi di file, invece usafind
akira

l'utilizzo findpuò anche restituire direttamente solo i file semplici per avviare la pipe.
mpez0,

1
Puoi farlo completamente in Bash usando anche al readposto di head: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen

4

Fai il grep:

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

Analizza i nomi dei file:

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

3

Puoi usare awk per questo:

$ 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

Ad eccezione dei file vuoti, questo script Perl sembra funzionare:

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

Non sono immediatamente sicuro di come gestire i file vuoti; Sarei tentato di trattarli come un caso speciale separato:

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

2

Prova questo

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

Verrà visualizzato un elenco di tutti i file che terminano in PHP, quindi esegui il ciclo. facendo eco al nome del file e quindi stampando la prima riga del file. Ho appena inserito

ti darà output come:

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

quindi puoi attaccare un grep normale alla fine per sbarazzarti di ciò che vuoi vedere e trovare solo le eccezioni

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

produzione:

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

4
Uso inutile di grep; usa "find -name '* .php'". Inoltre, uso pericoloso delle variabili: usa "trova -exec il tuo comando qui '{}' '+'" per evitare problemi con nomi di file "speciali". A parte questo, cita sempre le tue variabili: "head -1" $ i "", non "head -1 $ i".
Janmoesen,

for x in *.php;do echo $x \"head -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 "^<?"

dovrebbe fare quello che stai chiedendo.


Sì, ma se lo jolly, non mi dà nomi di file :( Anche "^ <?" Non ha funzionato per me, ho usato l'
opzione

2
@Phoshi catUso compulsivo , head -1 file.txt | grep "^<?"è abbastanza.
Benjamin Bannier,

1
Uso inutile di cat: - ((((
vwegert

Il gatto inutile è inutile :(
user13743

Trovo che sia molto più semplice ricordare i comandi se si mantiene tutto modulare e scomposto. So-cat- funzionerà, non so se commandprenderà il file come argomento. Potrebbe non essere strettamente necessario, ma non lo sto eliminando :)
Phoshi,

0

Questo:

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

ti dà qualcosa del genere:

  foo.xml: 0
  bla.txt: 1

ogni file che non contiene il tuo modello sarà "contrassegnato" con "1". puoi giocarci fino a quando non si adatta alle tue esigenze.


1
Devi citare i nomi dei file se potrebbero contenere spazi. E probabilmente vorrai perdere l'output da 'grep' a / dev / null. Puoi anche usare: head -1 "$i" | grep '^<?' || echo "$i"che stamperà il nome del file solo se è problematico.
Jonathan Leffler,

2
Ecco a cosa serve "grep -q". :-)
janmoesen

0

Fammi provare

trova-tipo f | awk '
{
 if (getline ret <$ 0) {
  if (ret ~ "^ <\\? $") {
   stampa "Buono [" $ 0 "] [" ret "]";
  }altro{
   stampa "Fail [" $ 0 "]";
  };
 }altro{
  stampa "vuoto [" $ 0 "]";
 };
 vicino ($ 0);
}'

nessuno ha detto che wak non era disponibile :-)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.