grep principio de archivo?


10

En un shell de Linux, quiero asegurarme de que un determinado conjunto de archivos comience con <?esa cadena exacta y sin otros caracteres al principio. ¿Cómo puedo grep o utilizar algún otro para expresar "el archivo comienza con"?


Editar: estoy poniendo un comodín en esto, y headno da un nombre de archivo en la misma línea, por lo que cuando lo aprendo, no veo el nombre de archivo. Además, "^<?"no parece dar los resultados correctos; Básicamente estoy obteniendo esto:

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

Todos los archivos son realmente buenos.

Respuestas:


11

En Bash:

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

Asegúrese de que sean archivos:

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


y dado que todos somos tan pedantes: no use el operador global en grandes cantidades de nombres de archivos, en su lugar usefind
akira

El uso findtambién puede devolver solo archivos planos directamente para iniciar la canalización.
mpez0

1
Puede hacerlo completamente en Bash cuando lo use en readlugar de headtambién: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen

4

Hacer el grep:

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

Analiza los nombres de archivo:

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

3

Puedes usar awk para esto:

$ 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

A excepción de los archivos vacíos, este script de Perl parece funcionar:

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

No estoy seguro de cómo manejar archivos vacíos; Estaría tentado a tratarlos como un caso especial separado:

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

2

Prueba esto

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

Esto obtendrá una lista de todos los archivos que terminan en PHP, luego los recorre. haciendo eco del nombre del archivo y luego imprimiendo la primera línea del archivo. Acabo de insertar

le dará salida 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

entonces puedes pegar un grep normal al final para deshacerte de lo que quieres ver y encontrar solo excepciones

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

salida:

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

44
Uso inútil de grep; use "find -name '* .php'". Además, uso peligroso de variables: use "find -exec your command here '{}' '+'" para evitar problemas con los nombres de archivos "especiales". Aparte de eso, siempre cite sus variables: "cabeza -1" $ i "", no "cabeza -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 "^<?"

debe hacer lo que pides.


Sí, pero si lo comodín, no me da nombres de archivo :( También "^ <?" No funcionó para mí, utilicé el
modificador

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

1
Uso inútil del gato: - ((((
vwegert

Gato inútil es inútil :(
user13743

Creo que es mucho más simple recordar comandos si mantiene todo modular y desglosado. Sé que cat funcionará, no sé si commandtomará el archivo como argumento. Puede que no sea estrictamente necesario, pero no lo voy a sacar :)
Phoshi

0

esta:

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

te da algo como esto:

  foo.xml: 0
  bla.txt: 1

cada archivo que no contenga su patrón será "marcado" con "1". puedes jugar con eso hasta que se ajuste a tus necesidades.


1
Debe citar los nombres de los archivos si pueden contener espacios. Y probablemente desee perder la salida de 'grep' a / dev / null. También puede usar: head -1 "$i" | grep '^<?' || echo "$i"que solo imprimirá el nombre del archivo si es problemático.
Jonathan Leffler

2
Para eso es "grep -q". :-)
janmoesen

0

Déjame probar esto

encontrar -tipo f | awk '
{
 if (getline ret <$ 0) {
  if (ret ~ "^ <\\? $") {
   print "Bueno [" $ 0 "] [" ret "]";
  }más{
   print "Fail [" $ 0 "]";
  };
 }más{
  print "empty [" $ 0 "]";
 };
 cerrar ($ 0);
} '

nadie dijo que wak no estaba disponible :-)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.