grep начало файла?

10

В оболочке linux я хочу убедиться, что все наборы файлов начинаются с <?этой точной строки и без других символов в начале. Как я могу grep или использовать какой-то другой, чтобы выразить «файл начинается с»?


Изменить: я подстановочный знак, и headне дает имя файла в той же строке, поэтому, когда я grep это, я не вижу имя файла. Кроме того, "^<?"кажется, не дает правильных результатов; в основном я получаю это:

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

Все файлы действительно хороши.

user13743
источник

Ответы:

11

В Баш:

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

Убедитесь, что они являются файлами:

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

janmoesen
источник
и так как мы все такие педантичные: не используйте оператор glob для огромного количества имен файлов, вместо этого используйтеfind
akira
Использование findможет также возвращать только простые файлы непосредственно для запуска канала.
mpez0
1
Вы можете полностью сделать это в Bash, когда используете readвместо этого headтоже: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen
4

Сделать grep:

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

Разобрать имена файлов:

$ head -n 1 * | grep -B1 "^<?" | sed -n 's/^==> \(.*\) <==$/\1/p'
foo
bar
baz
Приостановлено до дальнейшего уведомления.
источник
3

Вы можете использовать awk для этого:

$ 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
источник
3

За исключением пустых файлов, этот скрипт на Perl работает:

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

Я не сразу уверен, как обращаться с пустыми файлами; Я был бы склонен рассматривать их как отдельный особый случай:

find . -type f -size +0 -print0 |
    xargs -0 perl -e 'while (<>) { print "$ARGV\n" unless m/^<\?/; close ARGV; }'
Джонатан Леффлер
источник
2

Попробуй это

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

Это получит список каждого файла, оканчивающегося на PHP, а затем цикл по нему. повторяя имя файла и затем печатая первую строку файла. Я только что вставил

даст вам вывод, как:

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

тогда вы можете вставить обычный grep в конце, чтобы избавиться от того, что вы хотите увидеть, и найти только исключения

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

вывод:

gallery.php  ->
splash.php  -> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Рой Рико
источник
4
Бесполезное использование grep; используйте "find -name '* .php'". Также опасно использование переменных: используйте «find -exec your command here '{}' '+'», чтобы избежать проблем со «особыми» именами файлов. Кроме того, всегда указывайте свои переменные: "head -1" $ i "", а не "head -1 $ i".
Янмезен
for x in *.php;do echo $x \"head -n1 $ x\";done
user23307
1

Баш 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
источник
0
cat file.txt | head -1 | grep "^<?"

должен делать то, что вы просите.

Phoshi
источник
Да, но если я подстановочный знак, это не дает мне имена файлов :( Также «^ <?» У меня не работает, я использовал ключ -v.
user13743
2
@Phoshi Обязательное catиспользование, head -1 file.txt | grep "^<?"достаточно.
Бенджамин Банье
1
Бесполезное использование кошки: - (((
vwegert
Бесполезный кот бесполезен :(
user13743
Я считаю, что гораздо проще запоминать команды, если вы сохраняете все модульным и разбитым на части. Я знаю, что кот будет работать, я не знаю command, приму ли файл в качестве аргумента. Это может не быть строго необходимым, но я не
убираю
0

этот:

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

дает вам что-то вроде этого:

  foo.xml: 0
  bla.txt: 1

каждый файл, не содержащий ваш шаблон, будет помечен «1». Вы можете играть с этим, пока он не соответствует вашим потребностям.

Акира
источник
1
Вам нужно указать имена файлов, если они могут содержать пробелы. И вы, вероятно, захотите потерять вывод из 'grep' в / dev / null. Вы также можете использовать: head -1 "$i" | grep '^<?' || echo "$i"который будет печатать имя файла, только если это проблематично.
Джонатан Леффлер
2
Вот для чего "grep -q". :-)
Janmoesen
0

Позволь мне попробовать

найти тип f | awk '
{
 if (getline ret <$ 0) {
  если (в отставке ~ "^ <\\? $") {
   print "Good [" $ 0 "] [" ret "]";
  } Еще {
   print "Fail [" $ 0 "]";
  };
 } Еще {
  print "empty [" $ 0 "]";
 };
 близко ($ 0);
}»

никто не сказал, что Вак не было доступно :-)

user42723
источник