ค้นหาคำสั่งแจกแจงเอาต์พุตและอนุญาตการเลือก?


10

เมื่อฉันใช้findมักจะพบผลลัพธ์หลายรายการเช่น

find -name pom.xml
./projectA/pom.xml
./projectB/pom.xml
./projectC/pom.xml

ฉันมักจะต้องการเลือกเฉพาะผลลัพธ์ที่เฉพาะเจาะจง (เช่นedit ./projectB/pom.xml) มีวิธีในการแจกแจงfindเอาต์พุตและเลือกไฟล์ที่จะส่งผ่านไปยังแอปพลิเคชันอื่นหรือไม่? ชอบ:

find <print line nums?> -name pom.xml
1 ./projectA/pom.xml
2 ./projectB/pom.xml
3 ./projectC/pom.xml

!! | <get 2nd entry> | xargs myEditor

?

[แก้ไข] ฉันได้ชนกับเพอร์คิวลีอาร์ดบางตัวด้วยวิธีแก้ปัญหาบางอย่างที่กล่าวถึง ดังนั้นฉันต้องการอธิบายขั้นตอนในการทำซ้ำ:

git clone http://git.eclipse.org/gitroot/platform/eclipse.platform.swt.git
cd eclipse.platform.swt.git
<now try looking for 'pom.xml' and 'feature.xml' files>

[แก้ไข] วิธีแก้ไข 1 จนถึงตอนนี้การรวมกันของ 'nl' (เอาท์พุท enumirate), ส่วนหัวและหางดูเหมือนว่าจะทำงานถ้าฉันรวมพวกมันเข้ากับฟังก์ชั่นและใช้ $ (!!)

เช่น:

find -name pom.xml | nl   #look for files, enumirate output.

#I then define a function called "nls"
nls () {
  head -n $1 | tail -n 1
}

# I then type: (suppose I want to select item #2)
<my command> $(!!s 2)

# I press enter, it expands like: (suppose my command is vim)
vim $(find -name pom.xml |nls 2)

# bang, file #2 opens in vim and Bob's your uncle.

[แก้ไข] โซลูชันที่ 2 การใช้ "เลือก" ดูเหมือนว่าจะทำงานได้ดีเช่นกัน อดีต:

  findexec () {
          # Usage: findexec <cmd> <name/pattern>
          # ex: findexec vim pom.xml
          IFS=$'\n'; 
          select file in $(find -type f -name "$2"); do
                  #$EDITOR "$file"
                  "$1" "$file"
                  break
          done;  
          unset IFS
  }

มีการYour find command | head -TheNumberYouWantตอบสนองความต้องการของคุณหรือไม่ (ด้วยสายของคุณ: !! | head -2 | xargs myEditor)
ADDB

1
ตรวจสอบfzfมันผูกชนิดของการกระทำนี้ ^ T (ค่าเริ่มต้น)
Tavian บาร์นส์

คำตอบ:


16

การใช้bashงานในตัวselect:

IFS=$'\n'; select file in $(find -type f -name pom.xml); do
  $EDITOR "$file"
  break
done; unset IFS

สำหรับคำถาม "โบนัส" ที่เพิ่มในความคิดเห็น:

declare -a manifest
IFS=$'\n'; select file in $(find -type f -name pom.xml) __QUIT__; do
  if [[ "$file" == "__QUIT__" ]]; then
     break;
  else
     manifest+=("$file")
  fi
done; unset IFS
for file in ${manifest[@]}; do
    $EDITOR "$file"
done
# This for loop can, if $EDITOR == vim, be replaced with 
# $EDITOR -p "${manifest[@]}"

4
+1 สำหรับการเสนอสิ่งที่ฉันสงสัยว่าเป็นคำกริยาคำสั่งที่ใช้น้อยมาก
roaima

ฉันกำลังทำงานอยู่ ดูเหมือนจะไม่ได้วางไว้เป็นอย่างดีกับการเปลี่ยนแปลงselect IFS
DopeGhoti

3
อา. ( IFS=$'\n'; select file in $(find -maxdepth 2 -name '*.txt'); do echo "$file"; done; )
roaima

ฉันควรคิดถึงสตริงแบบ C ทำได้ดี!
DopeGhoti

1
ฉันขอขอบคุณข้อมูลเชิงลึกบางอย่าง @roaima: unix.stackexchange.com/questions/378282/…
DopeGhoti

3

สองฟังก์ชั่นเล็ก ๆ น้อย ๆ จะช่วยคุณแก้ปัญหานี้หากชื่อไฟล์ของคุณไม่มีการขึ้นบรรทัดใหม่หรืออักขระที่ไม่พิมพ์อื่น ๆ (มันจัดการกับชื่อไฟล์ที่มีช่องว่าง)

findnum() { find "$@" | sed 's!^\./!!' | nl; }
wantnum() { sed -nr "$1"'{s/^\s+'"$1"'\t//p;q}'; }

ตัวอย่าง

findnum -name pom.xml
     1  projectA/pom.xml
     2  projectB/pom.xml
     3  projectC/pom.xml

!! | wantnum 2
projectB/pom.xml

อย่างง่ายดายชื่อไฟล์ที่ชัดเจนpom.xmlจะไม่ประกอบด้วย whitespace (:
DopeGhoti

ดูเหมือนว่าจะมีข้อผิดพลาดบางอย่างในข้างต้น find -name pom.xml จะให้ผลลัพธ์จำนวนมาก แต่ findnum ให้ฉันเพียงบรรทัดเดียว เช่น. /features/org.eclipse.swt.tools.feature/pom.xml ./examples/org.eclipse.swt.examples.ole.win32/pom.xml ./examples/org.eclipse.swt.examples/pom .xml ./examples/org.eclipse.swt.examples.views/pom.xml ./examples/org.eclipse.swt.examples.launcher/pom.xml ./examples/org.eclipse.swt.examples.browser demos / pom.xml ./local-build/local-build-parent/pom.xml
Leo Ufimtsev

@Leo บนชุดข้อมูลเดียวกันคุณใช้งานfindnumอย่างไร
roaima

หวังว่าภาพหน้าจอนี้จะช่วยอธิบายปัญหา: i.imgur.com/hfneWJn.png คุณอาจสังเกตว่า feature.xml ให้ผลลัพธ์ 3 รายการ ด้วยคุณสมบัติ findnum ฉันได้รับข้อผิดพลาด ด้วย fundnum pom.xml จะพิมพ์ผลลัพธ์เดียวโดยที่ find -name pom.xml พิมพ์ผลลัพธ์ 3 รายการ ฉันอัปเดตคำถามเพื่ออธิบายวิธีรับชุดข้อมูล (มันเป็น repo คอมไพล์ง่ายๆ)
Leo Ufimtsev

1
@DopeGhoti ถึงแม้ว่ามันอาจจะอยู่ในไดเรกทอรีชื่อ whitespace d:
Wildcard

3

คุณสามารถได้รับส่วนหัวของผลรวมและต่อท้ายด้วย -1 สิ่งนี้สามารถไพพ์เอาต์พุตในคำสั่งหรือตัวแก้ไขอื่น ๆ เช่น

(รับ 100 บรรทัดและพิมพ์ที่ท่อสุดท้าย 100) ค้นหา | หัว -100 | หาง -1

xxx@prod01 (/home/xxx/.ssh) $ find .
.
./authorized_keys
./id_rsa
./id_rsa.pub
./id_rsa_b_x.pub
./id_rsa_a_y.pub
./known_hosts

xxx@prod01 (/home/xxx/.ssh) $ find . | head -3
.
./authorized_key
./id_rsa

xxx@prod01 (/home/xxx/.ssh) $ find . | head -3 | tail -1
./id_rsa    



eg: vim "$(find . | head -100 | tail -1)"

คุณจะได้รับการค้นหาลำดับที่ 100


1
ทางออกที่ง่ายน่าจะดีที่สุด คำตอบของคุณรวมกับ 'nl' และ '$ (!!)' ดูเหมือนจะใช้งานได้ดีจริง ๆ ฉันโพสต์รายละเอียดในคำถามของฉัน ขอบคุณสำหรับการตอบสนอง
Leo Ufimtsev

1

ถ้าเป้าหมายของคุณคือการแก้ไขไฟล์หลังจากการค้นหาให้ลองย้อย / กระสอบ

ตัวอย่าง:

$ sag skb_copy                                                                
sack__option is: -ag

============> running ag! <============

===> Current Profile: no_profile
===> Using flags: 
===> Searching under: /home/fklassen/git/pvc-appliance/kernel/drivers/ixgbevf
===> Searching parameters: skb_copy


/home/fklassen/git/pvc-appliance/kernel/drivers/ixgbevf/kcompat.c
[1] 195:        skb_copy_bits(skb, offset, buffer, len) < 0)

/home/fklassen/git/pvc-appliance/kernel/drivers/ixgbevf/kcompat.h
[2] 1774:   if (skb_copy_bits(skb, offset, buffer, len) < 0)
[3] 2321:#define skb_copy_to_linear_data(skb, from, len) \
[4] 2323:#define skb_copy_to_linear_data_offset(skb, offset, from, len) \

... จากนั้นเพื่อแก้ไขผลการค้นหาล่าสุด ....

F 4

ข้อดีคือคุณสามารถย้อนกลับไปแก้ไขผลการค้นหาแรกได้ในภายหลัง

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