grep début du fichier?


10

Dans un shell Linux, je veux m'assurer qu'un certain ensemble de fichiers commence par <?avoir cette chaîne exacte et aucun autre caractère au début. Comment puis-je utiliser grep ou utiliser un autre pour exprimer "le fichier commence par"?


Edit: je joker cela, et headne donne pas de nom de fichier sur la même ligne, donc quand je le salue, je ne vois pas le nom de fichier. De plus, "^<?"ne semble pas donner les bons résultats; en gros, je reçois ceci:

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

Tous les fichiers sont vraiment bons.

Réponses:


11

Dans Bash:

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

Assurez-vous que ce sont des fichiers:

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


et puisque nous sommes tous tellement pédants: n'utilisez pas l'opérateur glob sur d'énormes quantités de noms de fichiers, utilisez plutôtfind
akira

l'utilisation findne peut également renvoyer que des fichiers simples directement pour démarrer le canal.
mpez0

1
Vous pouvez le faire complètement dans Bash lorsque vous utilisez à la readplace de head: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen

4

Faites le grep:

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

Analysez les noms de fichiers:

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

3

Vous pouvez utiliser awk pour cela:

$ 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

Sauf pour les fichiers vides, ce script Perl semble fonctionner:

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

Je ne sais pas immédiatement comment gérer les fichiers vides; Je serais tenté de les traiter comme un cas spécial distinct:

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

2

Essaye ça

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

Cela obtiendra une liste de tous les fichiers se terminant en PHP, puis passera en boucle. en faisant écho au nom du fichier, puis en imprimant la première ligne du fichier. Je viens d'insérer

vous donnera une sortie comme:

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

alors vous pouvez coller un grep normal à la fin pour vous débarrasser de ce que vous voulez voir et trouver juste des exceptions

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

production:

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

4
Utilisation inutile de grep; utilisez "find -name '* .php'". Aussi, utilisation dangereuse des variables: utilisez "find -exec your command here '{}' '+'" pour éviter les problèmes avec les noms de fichiers "spéciaux". En dehors de cela, citez toujours vos variables: "head -1" $ i "", not "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 "^<?"

devrait faire ce que vous demandez.


Oui, mais si je le joker, cela ne me donne pas les noms de fichiers :( Aussi "^ <?" N'a pas fonctionné pour moi, j'ai utilisé le commutateur -v.
user13743

2
@Phoshi L' catutilisation compulsive head -1 file.txt | grep "^<?"suffit.
Benjamin Bannier

1
Utilisation inutile de chat: - (((
vwegert

Un chat inutile est inutile :(
user13743

Je trouve qu'il est beaucoup plus simple de se souvenir des commandes si vous gardez tout modulaire et ventilé. Je sais que ça fonctionnera, je ne sais pas si commandje prendrai le fichier en argument. Ce n'est peut-être pas strictement nécessaire, mais je ne le retire pas :)
Phoshi

0

ce:

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

vous donne quelque chose comme ça:

  foo.xml: 0
  bla.txt: 1

chaque fichier ne contenant pas votre motif sera "marqué" par "1". vous pouvez jouer avec cela jusqu'à ce qu'il corresponde à vos besoins.


1
Vous devez citer les noms de fichiers s'ils peuvent contenir des espaces. Et vous voudrez probablement perdre la sortie de 'grep' en / dev / null. Vous pouvez également utiliser: head -1 "$i" | grep '^<?' || echo "$i"qui n'imprimera le nom du fichier qu'en cas de problème.
Jonathan Leffler

2
C'est à cela que sert "grep -q". :-)
janmoesen

0

Laisse-moi essayer

trouver -type f | awk '
{
 if (getline ret <$ 0) {
  if (ret ~ "^ <\\? $") {
   print "Good [" $ 0 "] [" ret "]";
  }autre{
   print "Fail [" $ 0 "]";
  };
 }autre{
  print "empty [" $ 0 "]";
 };
 fermer (0 $);
} '

personne n'a dit que le wak n'était pas disponible :-)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.