grep đầu tập tin?


10

Trong shell linux, tôi muốn đảm bảo rằng một tập hợp các tệp nhất định bắt đầu bằng <?, có chuỗi chính xác đó và không có ký tự nào khác ở đầu. Làm cách nào tôi có thể grep hoặc sử dụng một số khác để thể hiện "tập tin bắt đầu bằng"?


Chỉnh sửa: Tôi ký tự đại diện này và headkhông đặt tên tệp trên cùng một dòng, vì vậy khi tôi grep nó, tôi không thấy tên tệp. Ngoài ra, "^<?"dường như không cho kết quả đúng; về cơ bản tôi đang nhận được điều này:

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

Tất cả các tập tin là thực sự tốt.

Câu trả lời:


11

Trong Bash:

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

Hãy chắc chắn rằng chúng là các tệp:

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


và vì tất cả chúng ta đều rất tầm thường: không sử dụng toán tử toàn cầu cho số lượng lớn tệp tên, thay vào đó hãy sử dụngfind
akira

sử dụng findcũng có thể chỉ trả lại các tập tin đơn giản để bắt đầu đường ống.
mpez0

1
Bạn hoàn toàn có thể làm điều đó trong Bash khi sử dụng readthay vì head: for file in *; do [ -f "$file" ] || continue; read < "$file"; [[ "$REPLY" =~ ^\<\? ]] || echo "$file"; done
janmoesen 17/03/2016


3

Bạn có thể sử dụng awk cho việc này:

$ 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

Ngoại trừ các tệp trống, tập lệnh Perl này dường như hoạt động:

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

Tôi không chắc chắn làm thế nào để xử lý các tập tin trống; Tôi muốn được coi họ là một trường hợp đặc biệt riêng biệt:

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

2

Thử đi

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

Điều này sẽ nhận được một danh sách của tất cả các tệp kết thúc bằng PHP, sau đó lặp qua nó. lặp lại tên tệp và sau đó in dòng đầu tiên của tệp. Tôi vừa chèn

sẽ cung cấp cho bạn đầu ra như:

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

sau đó bạn có thể dính một grep bình thường vào cuối để loại bỏ những gì bạn muốn thấy và chỉ tìm thấy ngoại lệ

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

đầu ra:

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

4
Sử dụng grep vô dụng; sử dụng "tìm -name '* .php'". Ngoài ra, việc sử dụng các biến nguy hiểm: sử dụng "find -exec lệnh của bạn tại đây '{}' '+'" để tránh các vấn đề với tên tệp "đặc biệt". Bên cạnh đó, luôn trích dẫn các biến của bạn: "head -1" $ i "", không phải "head -1 $ i".
janmoesen

for x in *.php;do echo $x \"đầu -n1 $ x\";done
dùng23307

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 "^<?"

nên làm những gì bạn đang yêu cầu.


Vâng, nhưng nếu tôi ký tự đại diện, nó không cho tôi tên tệp :( Ngoài ra "^ <?" Không hoạt động với tôi, tôi đã sử dụng công tắc -v.
user13743

2
@Phoshi catSử dụng bắt buộc , head -1 file.txt | grep "^<?"là đủ.
Benjamin Bannier

1
Việc sử dụng mèo vô dụng: - (((
vwegert

Con mèo vô dụng là vô dụng :(
user13743

Tôi thấy việc ghi nhớ các lệnh đơn giản hơn nhiều nếu bạn giữ mọi thứ mô đun và bị hỏng. Tôi biết con mèo sẽ hoạt động, tôi không biết liệu commandsẽ lấy tệp làm đối số hay không. Nó có thể không thực sự cần thiết, nhưng tôi không lấy nó ra :)
Phoshi

0

điều này:

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

cung cấp cho bạn một cái gì đó như thế này:

  foo.xml: 0
  bla.txt: 1

mọi tệp không chứa mẫu của bạn sẽ được "đánh dấu" bằng "1". bạn có thể chơi với nó cho đến khi nó phù hợp với nhu cầu của bạn.


1
Bạn cần trích dẫn tên tệp nếu chúng có thể chứa dấu cách. Và bạn có thể muốn mất đầu ra từ 'grep' thành / dev / null. Bạn cũng có thể sử dụng: head -1 "$i" | grep '^<?' || echo "$i"sẽ chỉ in tên tệp nếu có vấn đề.
Jonathan Leffler

2
Đó là những gì "grep -q" dành cho. :-)
janmoesen

0

Để tôi đi

tìm -type f | ôi '
{
 if (getline ret <$ 0) {
  if (ret ~ "^ <\\? $") {
   in "Tốt [" $ 0 "] [" ret "]";
  } khác {
   in "Thất bại [" $ 0 "]";
  };
 } khác {
  in "trống [" $ 0 "]";
 };
 đóng ($ 0);
} '

không ai nói wak không có sẵn :-)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.