grep início do arquivo?

10

Em um shell linux, quero ter certeza de que um certo conjunto de arquivos comece <?, com essa sequência exata e sem outros caracteres no início. Como posso grep ou usar outra para expressar "o arquivo começa com"?


Edit: Estou curingando isso e headnão dá um nome de arquivo na mesma linha; portanto, quando o grep, não vejo o nome do arquivo. Além disso, "^<?"parece não dar os resultados certos; basicamente eu estou entendendo isso:

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

Todos os arquivos são realmente bons.

user13743
fonte

Respostas:

11

No Bash:

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

Verifique se são arquivos:

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

janmoesen
fonte
e uma vez que são todos tão pedante: não use o operador glob em enormes quantidades de filesnames, em vez usarfind
akira
O uso findtambém pode retornar apenas arquivos simples diretamente para iniciar o pipe.
mpez0
1
Você pode completamente fazê-lo em Bash ao usar read, em vez de head, também: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen
4

Faça o grep:

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

Analise os nomes dos arquivos:

$ head -n 1 * | grep -B1 "^<?" | sed -n 's/^==> \(.*\) <==$/\1/p'
foo
bar
baz
Pausado até novo aviso.
fonte
3

Você pode usar o awk para isso:

$ 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
$
hlovdal
fonte
3

Exceto para arquivos vazios, este script Perl parece funcionar:

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

Não sei imediatamente como lidar com arquivos vazios; Eu ficaria tentado a tratá-los como um caso especial separado:

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

Tente isto

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

Isso obterá uma lista de todos os arquivos que terminam em PHP e, em seguida, passa por ele. ecoando o nome do arquivo e, em seguida, imprimindo a primeira linha do arquivo. Acabei de inserir

lhe dará uma saída como:

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

então você pode colocar um grep normal no final para se livrar do que deseja ver e encontrar apenas exceções

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

resultado:

gallery.php  ->
splash.php  -> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Roy Rico
fonte
4
Uso inútil do grep; use "find -name '* .php'". Além disso, uso perigoso de variáveis: use "find -exec your command here '{}' '+'" para evitar problemas com nomes de arquivos "especiais". Além disso, sempre cite suas variáveis: "head -1" $ i "", não "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
user31894
fonte
0
cat file.txt | head -1 | grep "^<?"

deve fazer o que você está pedindo.

Phoshi
fonte
Sim, mas se eu curinga, ele não me dar nomes de arquivo :( também "? ^ <" Não funcionou para mim, eu usei a opção -v.
user13743
2
@ Phoshi O catuso compulsivo head -1 file.txt | grep "^<?"é suficiente.
Benjamin Bannier
1
Uso inútil de gato: - (((
vwegert
O gato inútil é inútil :(
user13743
Acho muito mais simples lembrar comandos, se você mantiver tudo modular e dividido. Eu sei que vai funcionar, não sei se commandlevará o arquivo como argumento. Pode não ser estritamente necessário, mas eu não estou levando-o para fora :)
Phoshi
0

esta:

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

dá a você algo como isto:

  foo.xml: 0
  bla.txt: 1

todo arquivo que não contenha seu padrão será "marcado" com "1". você pode brincar com isso até que atenda às suas necessidades.

akira
fonte
1
Você precisa citar os nomes dos arquivos se eles puderem conter espaços. E você provavelmente desejaria perder a saída de 'grep' para / dev / null. Você também pode usar: head -1 "$i" | grep '^<?' || echo "$i"que só imprimirá o nome do arquivo se for problemático.
Jonathan Leffler
2
É para isso que serve "grep -q". :-)
janmoesen 12/03/10
0

Deixe-me tentar

encontre o tipo f | awk '
{
 if (getline ret <$ 0) {
  if (ret ~ "^ <\\? $") {
   imprima "Bom [" $ 0 "] [" ret "]";
  }outro{
   imprima "Fail [" $ 0 "]";
  };
 }outro{
  imprimir "vazio [" $ 0 "]";
 };
 fechar (US $ 0);
} '

ninguém disse que o wak não estava disponível :-)

user42723
fonte