คุณใช้นิพจน์ปกติกับคำสั่ง cp ใน Linux ได้อย่างไร


22

ฉันกำลังพยายามที่จะคัดลอกเฉพาะชุดย่อยของไฟล์จากไดเรกทอรีหนึ่งไปยังอีกโดยใช้แต่กำลังได้รับการต้อนรับด้วยข้อความcp cp: cannot stat [^\.php]': No such file or directoryมีวิธีใช้นิพจน์ทั่วไปโดยใช้cpคำสั่งเท่านั้นหรือไม่

คำตอบ:


29

เลขที่

cpคำสั่งไม่ได้มีความสามารถในการดำเนินการใด ๆ ของการขัดแย้งในฐานะการแสดงออกปกติ แม้กระทั่งไวด์การ์ดจะไม่ถูกจัดการ (หรือไฟล์ที่รันได้ส่วนใหญ่); ค่อนข้างจะถูกจัดการโดยเชลล์

cp test/* test2/ถูกขยายโดยการทุบตีจริง ๆ และสิ่งที่cpเห็นจริงๆสำหรับข้อโต้แย้งของมันคือcp test/file1 test/file2 test/file3 test2/(หรืออะไรก็ตามที่เหมาะสมตามเนื้อหาจริงของtest/)

นอกจากนี้ฉันไม่คิดว่านิพจน์ของคุณ[^\.php]จะตรงกับสิ่งที่คุณต้องการ (ไม่ตรงกับไฟล์ที่มี.php)

คุณอาจต้องการค้นหาfindยูทิลิตีเพื่อกรองรายการไฟล์ตามนิพจน์ทั่วไปจากนั้นใช้xargsเพื่อใช้รายการไฟล์ที่ส่งคืนไปยังcpคำสั่ง (การสันนิษฐานว่า find ไม่มีตัวจัดการในตัวสำหรับการคัดลอกไฟล์; ฉันไม่คุ้นเคยกับเครื่องมือ)

คุณอาจลอง:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

นี้กล่าวในการค้นหาไดเรกทอรีปัจจุบันซ้ำสำหรับไฟล์ที่ไม่ได้มี ".php" /destination/folder/ในเส้นทางและคัดลอกลงใน

ตามที่ร้องขอการแยกย่อยของอาร์กิวเมนต์ที่ระบุเพิ่มเติม:

  • . - ตำแหน่งเพื่อเริ่มการค้นหา - ในกรณีนี้คือไดเรกทอรีปัจจุบัน
  • ! - โอเปอเรเตอร์ "ไม่ใช่" กลับด้านผลลัพธ์ของการทดสอบถัดไป
  • -iregex- การทดสอบการแสดงออกปกติกรณีที่ไม่สำคัญ อาร์กิวเมนต์ต่อไปคือการแสดงออก
  • ".*\.php.*"- การจับคู่นิพจน์ทั่วไป<Anything>.php<Anything>- ไฟล์ใด ๆ ที่มี ".php" อยู่ที่ใดที่หนึ่งในพา ธ (หมายเหตุรวมถึงอยู่ในโฟลเดอร์ที่มี ".php" อยู่ในชื่อคุณจะต้องมีนิพจน์ที่ซับซ้อนมากขึ้นเพื่อให้ตรงกับไฟล์เท่านั้น)
  • -exec- ดำเนินการคำสั่งหากการทดสอบก่อนหน้านี้กลับมาจริง อาร์กิวเมนต์ถัดไปคือคำสั่งอาร์กิวเมนต์ที่เหลือทั้งหมดจะ;ถูกส่งไปยังคำสั่ง {}คืออาร์กิวเมนต์ที่พิเศษที่เป็นตัวแทนของชื่อไฟล์
  • cp - คำสั่งที่ find` ควรรันบนชื่อพา ธ ที่ตรงกันแต่ละชื่อ
  • {}- เส้นทางไปยังไฟล์ที่พบส่งผ่านไปยังcpอาร์กิวเมนต์เพื่อให้รู้ว่าไฟล์ใดที่จะคัดลอก
  • /destination/folder/- ส่งผ่านอาร์กิวเมนต์ไปยังcpบอกcpตำแหน่งที่ควรคัดลอกไฟล์ไป
  • \;- นี่คือเทอร์;มินอลที่-execกำลังค้นหา เราหลบหนีไปพร้อมกับ\เพื่อให้เปลือกของคุณไม่พยายามแยกมันและดึงมันเป็นอาร์กิวเมนต์ของคำสั่ง ( find)

มันค่อนข้างยากที่จะเขียนนิพจน์ปกติซึ่งตรงกับ "สายที่ไม่ได้.php" ดังนั้นเราจึงแทนที่จะบอกfindเพื่อค้นหาสตริงที่ไม่ประกอบด้วยแล้วกลับผลกับ.php!


2
find . -name [^\.php] -exec cp {} /path/to/location \;ระวังไฟล์ที่มีตัวอักษรพิเศษ
Rob

@Darth Android - ขอบคุณ ฉันไม่ทราบว่าcpและไบนารีอื่น ๆ ไม่สามารถขยายการแสดงผลปกติได้ คุณคิดอย่างละเอียดว่าตัวเลือกและอาร์กิวเมนต์แต่ละตัวมีความหมายอย่างไรในตัวอย่างตัวอย่างที่คุณให้ ฉันรู้ว่า.หมายถึงไดเรกทอรีปัจจุบัน แต่สิ่งที่!, {}, \;ฯลฯ อ้างถึงเช่นเดียวกับสิ่งที่พวกเขาหมายถึงอะไร? ยกตัวอย่างเช่นทำไมคุณต้องหลบหนี;?
PeanutsMonkey

@Rob - ไฟล์พิเศษหมายถึงอะไร?
PeanutsMonkey

@Rob - ฉันพยายามใช้นิพจน์ที่คล้ายกันเพื่อลบไฟล์ที่ระบุอย่างไรก็ตามมันสิ้นสุดด้วยการลบไฟล์ทั้งหมดในไดเรกทอรี คำสั่งของฉันเป็นเหตุฝืนใจของฉันที่จะใช้find . -name '[^\.txt]' -exec rm {} \; findอาจเป็นความผิดพลาดในส่วนของฉัน แต่ไม่แน่ใจในสิ่งที่ฉันทำผิด เท่าที่ความเข้าใจของฉัน{}อ้างถึงแต่ละไฟล์ที่พบโดยคำสั่งfind . -name '[^\.txt]'
PeanutsMonkey

คุณพยายามจับคู่อะไรกับ regex?
Rob

10

คุณสามารถใช้เครื่องมืออื่น ๆ จากคอนโซลเช่น grep และ xargs

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder

เป็นวิธีการ{}ที่แตกต่างกันกับที่-t?
PeanutsMonkey

2
ไม่มากในกรณีนี้ ไวยากรณ์สำรองสำหรับ xargs จะเป็น 'xargs cp {} destination_folder' ไวยากรณ์ cp มาตรฐานใช้แหล่งข้อมูลหนึ่งแหล่งหรือหลายแหล่งและปลายทางหนึ่งปลายทางในท้ายที่สุดเมื่อคุณใช้ตัวเลือก -t คุณสามารถระบุปลายทางหลังจาก -t จากนั้นใช้ส่วนที่เหลือของแหล่งที่มา ฉันเพิ่งพบว่ามีตัวเลือก -t สะดวกกว่าในกรณีนี้ ในตัวอย่างอื่น ๆ {} จะถูกแทนที่ด้วยสิ่งที่ถูกส่งไปยัง xargs (stdin) ในกรณีนี้ชื่อไฟล์
0xAF

-1

คุณสามารถเรียกใช้คำสั่งต่อไปนี้ใช้งานง่าย:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

Haa เย็น !!

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