คัดลอกรายการไฟล์


35

list.txtฉันมีรายชื่อของไฟล์คั่นด้วยช่องว่างในแฟ้ม ฉันต้องการคัดลอกไปยังโฟลเดอร์ใหม่

ฉันพยายามทำ:

cp `cat list.txt` new_folder

แต่มันไม่ทำงาน

คุณจะทำอย่างไร

ปรับปรุง:

ขอบคุณสำหรับคำตอบที่น่าสนใจทั้งหมดของคุณ ฉันไม่ได้ขออะไรมากมาย :)

หลังจากลองวิธีแก้ปัญหาข้างต้นเป็นครั้งที่สองดูเหมือนว่าจะcpพิมพ์วิธีใช้เนื่องจากโฟลเดอร์new_folderยังไม่มีอยู่! ขออภัยดูเหมือนว่าจะเป็นข้อผิดพลาดที่โง่ ... เมื่อฉันสร้างโฟลเดอร์มาก่อนมันใช้งานได้

อย่างไรก็ตามฉันได้เรียนรู้มากมายจากคำตอบและวิธีแก้ปัญหาทั้งหมดของคุณขอบคุณสำหรับเวลาที่คุณเขียน


ให้ฉันได้สิ่งหนึ่งที่ชัดเจน: รายการมีชื่อไฟล์ทั้งหมดในหนึ่งบรรทัดคั่นด้วยช่องว่างหรือไม่ หรือชื่อแต่ละชื่อในบรรทัดแยกกัน
Telemachus

ทั้งหมดในมะนาวเดียวคั่นด้วยช่องว่าง วิธีแก้ปัญหาของ Doug ทำงานได้ดี :) ขอบคุณสำหรับคำตอบ
Klaus

มันตลกดี ... ฉันทดสอบวิธีแก้ปัญหาของฉันด้วยบรรทัดที่ชื่อแต่ละชื่อแยกกัน
Doug Harris

"มันใช้งานไม่ได้" ไม่มีความหมายมากนัก แน่นอนว่ามันไม่ได้ทำงาน มันใช้งานได้ดีสำหรับฉัน
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

ขออภัยมันแสดงให้เห็นถึงความช่วยเหลือในการใช้ cp ดูการอัปเดตของฉันด้านบน
Klaus

คำตอบ:


34

ลองใช้ xargs:

cat list.txt | xargs -J % cp % new_folder

ปรับปรุง:

ฉันทำสิ่งนี้ใน OS X ซึ่งมีเวอร์ชันแตกต่างจาก GNU / Linux xargsซึ่งมาจากfindutils GNUไม่ได้-Jแต่มันก็มี-Iซึ่งคล้าย (เดนนิสวิลเลียมสันชี้ให้เห็นในความคิดเห็น) xargs เวอร์ชัน OS X มีทั้งคู่-Iและ-Jมีพฤติกรรมแตกต่างกันเล็กน้อย - อาจใช้งานได้สำหรับคำถามดั้งเดิมนี้

$ cat list.txt
one
two.txt
three.rtf

$ cat list.txt | xargs -J % echo cp % new_folder
cp one two.txt three.rtf new_folder

$ cat list.txt | xargs -I % echo cp % new_folder
cp one new_folder
cp two.txt new_folder
cp three.rtf new_folder

3
ฉันxargsไม่มี-Jมัน-Iที่ดูเหมือนจะทำสิ่งเดียวกัน xargsคุณมีระบบปฏิบัติการรุ่น / รุ่นใดและรุ่นใด?
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

ฉันทดสอบสิ่งนี้ใน Mac OS X 10.6 (หรือที่เรียกว่าเสือดาวหิมะ) ดังนั้นทุกรุ่นของ xargs ก็มาพร้อมกับ OS การรันxargs --versionจะส่งคืนข้อความแสดงข้อผิดพลาดการใช้งาน อาจเป็น xargs รุ่น BSD การใช้งาน-Iและ-Jแตกต่างกันอย่างละเอียด ฉันจะอัปเดตคำตอบของฉันด้วยตัวอย่างที่จัดรูปแบบไว้อย่างดี
Doug Harris

ใช่ฉันทำงานกับ Mac OSX 10.6 ขอขอบคุณสำหรับความแม่นยำเกี่ยวกับ-Jและ-I:)
เคลาส์

นั่นเป็นเคล็ดลับที่ดีในการใช้เสียงก้องเพื่อตรวจสอบคำสั่งของคุณก่อนที่จะเรียกใช้
เลียม

1
ใช้คำสั่งข้างต้นเดียวกันกับการเปลี่ยนแปลงที่จำเป็นเท่านั้นฉันจะคัดลอกไฟล์พร้อมกับสร้างไดเรกทอรีและส่วนย่อยที่พวกเขาอยู่ในคั่นด้วยเครื่องหมายทับได้อย่างไร
Vicky Dev

54

ไม่ต้องการcatเลย:

xargs -a list.txt cp -t new_folder

หรือใช้ตัวเลือกแบบยาว:

xargs --arg-file=list.txt cp --target-directory=new_folder

นี่คือบางรุ่นของเชลล์ โปรดทราบว่าตัวแปรบางตัวไม่มีการอ้างอิงหรือforมีการใช้ลูปเป็นพิเศษเนื่องจาก OP ระบุว่าชื่อไฟล์เป็นตัวคั่นช่องว่าง เทคนิคเหล่านี้บางอย่างจะใช้ไม่ได้กับอินพุตชื่อไฟล์ต่อบรรทัดซึ่งชื่อไฟล์มีพื้นที่สีขาว

ทุบตี:

for file in $(<list.txt); do cp "$file" new_folder; done

หรือ

cp $(<list.txt) new_folder

sh (หรือ Bash):

# still no cat!
while read -r line; do for file in $line; do cp "$file" new_folder; done; done < list.txt

หรือ

# none here either
while read -r line; do cp $line new_folder; done < list.txt

หรือ

# meow
for file in $(cat list.txt); do cp "$file" new_folder; done

หรือ

# meow
cp $(cat list.txt) new_folder

noob คำถาม: ทำไม-tจำเป็นxargs -a list.txt cp -t new_folder?
Yibo Yang

1
@YiboYang: -tตัวเลือกcpคือ มันคัดลอกข้อโต้แย้งที่มาทั้งหมดลงในไดเรกทอรีเป้าหมายที่ระบุ ที่นี่อนุญาตให้ระบุเป้าหมายก่อนหน้าแหล่งที่จะถูกเพิ่มโดยxargsคำสั่ง
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

สิ่งนี้มีประโยชน์ แต่จะเกิดอะไรขึ้นถ้า list.txt มีเส้นทางไฟล์และโฟลเดอร์แบบผสม ในกรณีนั้นคำสั่งจะทำงานไม่ถูกต้อง โดยจะรายงาน "การข้ามไดเรกทอรี ... " และหากระบุ -R ในคำสั่ง cp ข้อผิดพลาด "ไม่ใช่ไดเรกทอรี" จะถูกรายงานทันทีที่พบไฟล์แรกในรายการ
Bemipefe

7

ก่อนหน้านี้ฉันมีคำตอบที่น่าอาย แต่คำตอบของเดนิสทำให้ฉันนึกถึงว่าฉันพลาดสิ่งพื้นฐานที่สุดไปแล้ว ดังนั้นฉันจึงลบคำตอบดั้งเดิมของฉัน แต่เนื่องจากไม่มีใครพูดสิ่งพื้นฐานนี้มากฉันคิดว่ามันคุ้มค่าที่จะวางไว้ที่นี่

คำถามเดิมคือ "ฉันมีไฟล์ข้อความที่มีรายชื่อไฟล์ที่คั่นด้วยช่องว่างฉันจะคัดลอกไฟล์เหล่านั้นไปยังไดเรกทอรีเป้าหมายเดียวได้อย่างไร" ในตอนแรกสิ่งนี้อาจดูยุ่งยากหรือซับซ้อนเนื่องจากคุณคิดว่าคุณจะต้องแยกรายการออกจากไฟล์ในลักษณะเฉพาะ แต่เมื่อเปลือกกระบวนการบรรทัดคำสั่ง, สิ่งแรกที่มันไม่สามารถแยกรายการอาร์กิวเมนต์ลงในราชสกุลและ (ที่นี่ใครบิตได้กล่าวทันที) พื้นที่แยกราชสกุล (ขึ้นบรรทัดใหม่ยังแยกโทเค็นซึ่งเป็นสาเหตุให้การทดสอบของดั๊กแฮร์ริสด้วยรายการที่คั่นด้วยบรรทัดใหม่มีผลลัพธ์เหมือนกัน) นั่นคือเชลล์คาดหวังและสามารถจัดการรายการคั่นด้วยช่องว่างได้แล้ว

ดังนั้นสิ่งที่คุณต้องทำที่นี่คือใส่รายการที่คั่นด้วยช่องว่าง (ที่คุณมี) ในสถานที่ที่เหมาะสมในคำสั่งของคุณ คำสั่งของคุณเป็นรูปแบบบางอย่างนี้:

cp file1 file2 file3...file# target

รอยย่นเพียงอย่างเดียวคือคุณต้องการรับรายการไฟล์ 1 ถึง # จากไฟล์ข้อความของคุณ

เมื่อเดนนิสชี้ให้เห็นในความคิดเห็นของเขาความพยายามเริ่มต้นของคุณ ( cpcat list.txt new_folder) ควรจะใช้งานได้แล้ว ทำไม? เนื่องจากคำสั่งภายในcat list.txtถูกประมวลผลก่อนโดยเชลล์และขยายเข้าไปfile1 file2 file3...file#ซึ่งเป็นสิ่งที่เชลล์ต้องการและต้องการที่ส่วนคำสั่งนั้น ถ้ามันไม่ทำงาน (1) คุณมีการพิมพ์ผิดหรือ (2) ชื่อไฟล์ของคุณแปลกไปอย่างใดอย่างหนึ่ง (มีช่องว่างหรือตัวอักษรผิดปกติอื่น ๆ )

เหตุผลที่คำตอบทั้งหมดของ Dennis นั้นเป็นเพียงการให้รายชื่อไฟล์ที่จำเป็นสำหรับcpการทำงานโดยวางรายการนั้นไว้ในคำสั่งทั้งหมด อีกครั้งคำสั่งนี้อยู่ในโครงสร้าง:

cp list-of-files target_directory

มันง่ายที่จะดูว่าทั้งหมดนี้มารวมกันในรุ่นนี้ได้อย่างไร:

cp $(<list.txt) new_folder

$()ทำให้เชลล์รันคำสั่งภายในวงเล็บจากนั้นแทนที่เอาต์พุตที่จุดนั้นในบรรทัดที่ใหญ่กว่า จากนั้นเชลล์จะรันบรรทัดโดยรวม โดยวิธีการที่$()เป็นรุ่นที่ทันสมัยมากขึ้นของสิ่งที่คุณกำลังทำอยู่แล้วกับ backticks ( `) ถัดไป: <เป็นตัวดำเนินการเปลี่ยนเส้นทางไฟล์ มันบอกเชลล์ให้ดัมพ์เนื้อหาของlist.txtไปยังอินพุตมาตรฐาน เนื่องจาก$()บิตได้รับการประมวลผลก่อนนี่คือสิ่งที่เกิดขึ้นในขั้นตอน:

  1. cp $(<list.txt) new_folder # split line into three tokens: cp, $(<list.txt), new_folder
  2. cp file1 file2 file3...file# new_folder # substitute result of $(<list.txt) into the larger command

เห็นได้ชัดว่าขั้นตอนที่ 2 เป็นเพียงcpคำสั่งปกติที่คุณต้องการ

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


@ Klaus คุณยินดีมาก เพื่อความซื่อสัตย์ฉันรู้สึกรำคาญตัวเองเป็นส่วนใหญ่หลังจากอ่านคำตอบของเดนนิสและตระหนักว่าฉันพลาดส่วนสำคัญของปัญหาไปโดยสิ้นเชิง ทางออกที่คุณชอบคือจากที่นั่นเช่นกัน
Telemachus

นี่เป็นคำตอบที่เก่ามาก แต่ถ้าคุณต้องการสร้างโครงสร้างโฟลเดอร์ใหม่คุณจำเป็นต้องมีการ--parentsตั้งค่าสถานะ คุณสามารถทำให้มัน verbose กับ-vบันทึกสิ่งที่ถูกคัดลอก หากคุณต้องการเก็บสิทธิ์คุณต้องมี-aหรือ-pตั้งค่าสถานะ กล่าวคือcp --parents -av $(<list.txt) new_folderกล่าวคือนี่คือทั้งหมดที่สมมติว่ารายชื่อไฟล์ของคุณเป็นไฟล์จริง ๆ ทั้งหมดมิฉะนั้นคุณอาจต้อง-rตั้งค่าสถานะให้ทำการเรียกคืน
dhaupin

@dhaupin ที่จริงแล้ว OP ระบุว่าเขาอยู่ใน macOS ดังนั้นสำหรับสิ่งที่คุ้มค่า--parentsธงไม่ได้อยู่ที่นั่น รุ่น (มาจาก BSD) cpมีเพียงตัวเลือกสั้น ๆ เท่านั้นไม่ใช่ตัวเลือกแบบยาวของ GNU สำหรับลักษณะ BSD cpแฟล็กสำหรับการทำซ้ำแบบเรียกซ้ำจะเป็นตัวพิมพ์ใหญ่-Rไม่ใช่ตัวพิมพ์เล็ก
Telemachus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.