grep จุดเริ่มต้นของไฟล์?


10

ในเชลล์ลินุกซ์ฉันต้องการตรวจสอบให้แน่ใจว่าชุดของไฟล์ทั้งหมดเริ่มต้นด้วย<?การมีสตริงที่แน่นอนและไม่มีอักขระอื่น ๆ ที่จุดเริ่มต้น ฉันจะ 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; }'

2

ลองสิ่งนี้

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

นี่จะเป็นรายการของทุก ๆ ไฟล์ที่ลงท้ายด้วย PHP จากนั้นวนซ้ำ echoing ชื่อไฟล์แล้วพิมพ์บรรทัดแรกของไฟล์ ฉันเพิ่งแทรก

จะให้ผลลัพธ์เช่น:

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 คำสั่งของคุณที่นี่ '{}' '+'" เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับชื่อไฟล์ "พิเศษ" นอกจากนั้นให้อ้างอิงตัวแปรของคุณเสมอ: "head -1" $ i "" ไม่ใช่ "head -1 $ i"
janmoesen

for x in *.php;do echo $x \"head -n1 $ x\";done
23307

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

ควรทำสิ่งที่คุณขอ


ใช่ แต่ถ้าฉันใช้สัญลักษณ์แทนมันไม่ให้ชื่อไฟล์กับฉัน :( เช่นกัน "^ <?" ไม่ได้ผลสำหรับฉันฉันใช้สวิตช์ -v
user13743

2
@Phoshi บังคับ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

ให้ฉันไปที่นี้

ค้นหาประเภท f | awk '
{
 if (getline ret <$ 0) {
  ถ้า (เกษียณ ~ "^ <\\? $") {
   พิมพ์ "ดี [" $ 0 "] [" ret "]";
  }อื่น{
   พิมพ์ "ล้มเหลว [" $ 0 "]";
  };
 }อื่น{
  พิมพ์ "empty [" $ 0 "]";
 };
 ใกล้ ($ 0);
}'

ไม่มีใครพูดว่า wak ใช้ไม่ได้ :-)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.