grep початок файлу?


10

У оболонці linux, я хочу переконатися, що певний набір файлів починається з <?, що має точну рядок і ніяких інших символів на початку. Як я можу grep або використовувати інші, щоб висловити "файл починається з"?


Редагувати: я підкреслюю це, і head не дає ім'я файлу на тому ж рядку, тому, коли я grep це, я не бачу ім'я. Також, "^<?" схоже, не дає правильних результатів; в основному я отримую це:

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

Всі файли дійсно хороші.

Відповіді:


11

У Bash:

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

Переконайтеся, що вони є файлами:

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


і оскільки ми всі настільки педантичні: не використовуйте оператора glob на величезній кількості назв файлів, а не використовуйте find
akira

використання find Також можна повернути тільки прості файли безпосередньо для запуску труби.
mpez0

1
Ви можете повністю зробити це в Bash під час використання read замість headтеж: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen

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
$

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; }'

3

Виконайте grep:

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

Визначте назви файлів:

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

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 '". Крім того, небезпечне використання змінних: use "find -exec your command here" {} '' + '', щоб уникнути проблем з "спеціальними" іменами файлів. Окрім цього, завжди цитуйте ваші змінні: "head -1" $ i "", а не "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 "^<?"

повинен робити те, що ви просите.


Так, але якщо я його замінюю, це не дає мені імен файлів :( Також "^ & lt ;?" не працював для мене, я використовував перемикач -v.
user13743

2
@Phoshi Compulsive cat використання, head -1 file.txt | grep "^<?" достатньо.
Benjamin Bannier

1
Непридатне використання кота: - (((
vwegert

Непридатний кіт марний :(
user13743

Я вважаю, що набагато простіше запам'ятовувати команди, якщо ви тримаєте все модульне і розбито. Я знаю - кішка працюватиме, я не знаю, якщо command візьме файл як аргумент. Це може бути не зовсім необхідним, але я не беру його:
Phoshi

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" який буде друкувати тільки ім'я файлу, якщо це проблематично.
Jonathan Leffler

2
Ось для чого "grep -q". :-)
janmoesen

0

Дозвольте мені піти на це

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

ніхто не сказав, що wak недоступний :-)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.