มันเป็น UUOC (ใช้แมวไร้ประโยชน์) เพื่อเปลี่ยนเส้นทางไฟล์หนึ่งไปยังอีกไฟล์หนึ่งหรือไม่?


36

ถ้าผมต้องการที่จะทำให้เนื้อหาของfile2ตรงกับเนื้อหาของผมเห็นได้ชัดว่าสามารถทำงานเพียงfile1cp file1 file2

แต่ถ้าผมต้องการที่จะรักษาทุกอย่างที่เกี่ยวกับการfile2 ยกเว้นเนื้อหาเจ้าของสิทธิ์คุณสมบัติการขยาย, ACL ของการเชื่อมโยงอย่างหนัก ฯลฯ ฯลฯ แล้วฉันจะไม่ต้องการที่จะทำงานcp. * ในกรณีที่ว่าผมแค่อยากจะป๋อม เนื้อหาของเข้าfile1file2

ดูเหมือนว่าต่อไปนี้จะทำ:

< file1 > file2

แต่มันไม่ทำงาน file2ถูกตัดทอนเป็นไม่มีอะไรและไม่ได้เขียนถึง อย่างไรก็ตาม

cat < file1 > file2

ไม่ทำงาน

มันทำให้ฉันประหลาดใจว่ารุ่นแรกไม่ทำงาน

รุ่นที่สองเป็น UUOC หรือไม่ มีวิธีการทำเช่นนี้โดยไม่ต้องใช้คำสั่งเพียงแค่ใช้การเปลี่ยนเส้นทาง?

หมายเหตุ: ฉันทราบว่า UUOC เป็นจุดอวดความรู้มากกว่ารูปแบบการต่อต้านที่แท้จริง

* ตามที่ค้นพบ tniles09 จริง ๆแล้วcp จะใช้งานได้ในกรณีนี้


3
ไม่ว่า< file1 > file2สิ่งที่คุณต้องการจะขึ้นอยู่กับเปลือก
Michael Homer

13
ดีก็คือใช้ประโยชน์ของ<...
jwodder

2
สิ่งที่เป็นต่อต้านรูปแบบ ?
mikeserv

6
@ jwodder - นั่นไม่จริง โดยเฉพาะอย่างยิ่งเมื่อคุณกำลังพูดถึงสำเนา พิจารณาสิ่งที่เกิดขึ้นเมื่อfile1ไม่มีอยู่หรือไม่สามารถอ่านได้และคุณเปิด< ก่อนที่ >จะเปิดเอาต์พุตแล้วพิจารณาว่าเกิดอะไรขึ้นเมื่อคุณอนุญาตให้catลองเปิด
mikeserv

3
@JonathanLeffler ใน zsh คำสั่งว่างที่มีการเปลี่ยนเส้นทางจะเรียกใช้cat(โดยค่าเริ่มต้น) โดยพื้นฐานแล้วจะใช้คำสั่งที่สอง ดูคำตอบของStéphane Chazelasด้านล่างเพื่อรับข้อมูลเพิ่มเติมเกี่ยวกับความคิดเห็น
Michael Homer

คำตอบ:


58

cat < file1 > file2ไม่ใช่ UUOC คลาสสิก<และ>ทำการเปลี่ยนเส้นทางซึ่งสอดคล้องกับการทำซ้ำไฟล์อธิบายในระดับระบบ การทำซ้ำตัวอธิบายไฟล์ด้วยตัวเองไม่ได้ทำสิ่งใด (การ>เปลี่ยนเส้นทางที่เปิดด้วยO_TRUNCดังนั้นเพื่อความแม่นยำการเปลี่ยนเส้นทางเอาต์พุตจะตัดทอนไฟล์เอาต์พุต) อย่าปล่อยให้< >สัญลักษณ์สับสน การเปลี่ยนเส้นทางไม่ย้ายข้อมูล - พวกเขากำหนด file descriptors ให้กับ file descriptors อื่น ๆ

ในกรณีนี้คุณเปิดfile1และกำหนด file descriptor ให้ file descriptor 0( <file1== 0<file1) file2และกำหนด file descriptor นั้นให้ file descriptor 1( >file2== 1>file2)

ตอนนี้คุณมีตัวอธิบายไฟล์สองตัวแล้วคุณต้องมีกระบวนการที่จะทำการขุดข้อมูลระหว่างสองและนั่นคือสิ่งที่catมีไว้สำหรับ


11
อาจจะเป็นแค่ฉัน แต่ส่วนที่ฉันชอบที่สุดของคำตอบนี้คือการใช้คำว่า "พลั่ว" ของคุณ :) ชัดเจนมากขอบคุณ
ไวด์การ์ด

1
@ Wildcard ฉันต้องการ "ปั๊ม" เหนือ "พลั่ว" แต่ก็ยังเป็นคำที่ดี +1
เมห์rdad

ทำไมพลั่วเป็นคำที่ดี?
bubakazouba

1
หนึ่งพลั่วกองดินหนึ่งพลั่วเต็มในเวลาจากกองหนึ่งไปยังอีกขณะที่ข้อมูลจะถูกคัดลอกบัฟเฟอร์โดยบัฟเฟอร์ มันเป็นการเปรียบเทียบที่ดี
bsd

1
ในประโยคแรกของคุณคุณบอกว่าไฟล์ descriptors กำลังถูกทำซ้ำ พวกเขากำลังทำซ้ำหรือกำหนดใหม่ (ตามวรรคสองของคุณและพฤติกรรมของคุณลักษณะดูเหมือนจะบ่งบอก)?
Greg Bell

17

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

อย่างไรก็ตามในระบบ GNU cp --no-preserve=all file1 file2หลักฐานครั้งแรกของคุณมีวิธีอื่นที่ใช้ได้: ลองใช้นี่ฉันคิดว่ามันจะเป็นไปตามสถานการณ์ที่คุณอธิบายไว้ (เช่นการแก้ไขเนื้อหาfile2ในขณะที่ไม่แก้ไขคุณลักษณะ)

ตัวอย่าง :

$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 16 Dec 16 12:21 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Lookout, world!
    Hello, world!
$ cp --no-preserve=all fred fezzik 
$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 14 Dec 16 12:22 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Hello, world!
    Hello, world!

UPDATE อันที่จริงผมเพิ่งสังเกตเห็นว่าระบบของฉันcpด้วยตัวเองดูเหมือนว่าจะรักษาคุณลักษณะเว้นแต่-aหรือ-pมีการระบุไว้ ฉันใช้เปลือกทุบตีและแกนกลาง GNU ฉันเดาว่าคุณเรียนรู้สิ่งใหม่ทุกวัน ...


ผลการทดสอบ (โดย Wildcard) รวมถึงฮาร์ดลิงก์และการอนุญาตที่แตกต่าง:

$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 file2
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the original contents of file2
$ cp file1 file2
$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 file2
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the contents of file1
$ 

ดี ฉันรันการทดสอบของตัวเองรวมถึงฮาร์ดลิงก์และการอนุญาตที่แตกต่างกันและดูเหมือนว่าคุณถูกต้อง
สัญลักษณ์ตัวแทน

เพิ่มผลการทดสอบของฉัน; หวังว่าคุณจะไม่รังเกียจ :) ฉันไม่ได้ทดสอบ ACLs หรือแอตทริบิวต์เพิ่มเติม แต่เนื่องจากหมายเลข inodeนั้นได้รับการเก็บรักษาไว้ฉันมั่นใจว่า 99% จะเป็นเช่นนั้น
สัญลักษณ์แทน

ดี ... ไม่รังเกียจเลย :-)
tniles

13

ในzshเปลือกที่ทำงานเปลือกไม่วิงวอน< file1 > file2cat

สำหรับบรรทัดคำสั่งที่ประกอบด้วยการเปลี่ยนเส้นทางเท่านั้นและไม่มีคำสั่งหรือการมอบหมายให้zshเรียกใช้$NULLCMD( catตามค่าเริ่มต้น) ยกเว้นว่ามีการเปลี่ยนเส้นทางเพียงอย่างเดียวคือ<กรณีที่$READNULLCMD( pagerโดยค่าเริ่มต้น) แทน (นั่นคือถ้าzshอยู่ในshหรือcshจำลองในกรณีที่มันทำงานเหมือนเปลือกหอยมันเลียนแบบ)

ดังนั้น:

< file1 > file2

เป็นเช่นเดียวกับ

cat < file1 > file2

และ

< file1

เป็นเช่นเดียวกับ

pager < file1

สำหรับเรกคอร์ดไวยากรณ์นี้ใช้ไม่ได้กับ ksh93
fpmurphy

8
< from > to

ไม่ทำงานเพราะไม่มีคำสั่งอยู่ที่นั่น ไม่มีกระบวนการ เชลล์เปิด / สร้างไฟล์และจัดเรียงการเปลี่ยนเส้นทาง (หมายถึงไฟล์ descriptors ที่อ้างถึงไฟล์เหล่านี้ถูกปลูกเป็น 0 และ 1: อินพุตมาตรฐานและเอาต์พุตมาตรฐาน) แต่ไม่มีสิ่งใดในการดำเนินการวนรอบเพื่ออ่านจากอินพุตมาตรฐานและเขียนไปยังเอาต์พุตมาตรฐาน

zshทำให้การทำงานนี้โดยการแทนคำสั่งที่ผู้ใช้กำหนดในกรณีนี้ "คำสั่งโมฆะ" คำสั่งไม่สามารถมองเห็นได้ในบรรทัดคำสั่ง แต่ยังคงมีอยู่ กระบวนการถูกสร้างขึ้นสำหรับมันและทำงานในลักษณะเดียวกัน NULLCMDเป็นcatค่าเริ่มต้นดังนั้น< from > toจริงๆแล้วหมายถึง cat < from > toในzshเว้นแต่NULLCMDจะมีการตั้งค่าอย่างอื่น มันเป็นคำสั่ง "implicit cat"

"การใช้ cat ไร้ประโยชน์" เกิดขึ้นเมื่อcatใช้เป็นสื่อกลางในการอ่านจากไฟล์และป้อนข้อมูลไปยังกระบวนการอื่นซึ่ง descriptor ไฟล์สามารถเชื่อมต่อกับไฟล์ต้นฉบับได้

หากcatสามารถถอดออกได้จากสถานการณ์เช่นนั้นคำสั่งที่เหลือสามารถยังคงทำงานเดียวกันมันก็ไร้ประโยชน์ หากไม่สามารถถอดออกได้แสดงว่าไม่มีประโยชน์อะไรเลย

# useless, removable:
$ cat archive.tar | tar tf -    #  -->  tar tf archive.tar

# not removable (in POSIX shell):
$ cat > file
abc
[Ctrl-D]

# likewise:
STRING=$(cat file)

catที่เป็นreplacableไม่ได้เป็นสิ่งเดียวกัน ตัวอย่างเช่นแทนที่จะcat > fileเราสามารถใช้vi fileเพื่อสร้างไฟล์ ไม่นับเป็นการลบออกcatในขณะที่ใช้สิ่งที่เหลืออยู่เพื่อให้งานเดียวกันสำเร็จ

ถ้าcatเป็นคำสั่งเดียวในไปป์ไลน์แน่นอนว่ามันไม่สามารถลบได้ การจัดเรียงสิ่งที่เหลืออยู่จะไม่ทำงานเทียบเท่า

สคริปเชลล์บางตัวใช้catเพราะพวกมันคิดว่ามันช่วยให้พวกมันย้ายตัวถูกดำเนินการอินพุตใกล้กับด้านซ้ายของบรรทัดคำสั่ง อย่างไรก็ตามการเปลี่ยนเส้นทางสามารถอยู่ที่ใดก็ได้ในบรรทัดคำสั่ง:

# If you're so inclined:
# move source archive operand to the left without cat:
$ < archive.tar tar xf - > listing

btw คุณไม่ต้องใช้f -น้ำมันดิน เป็นเพียงtar xf - tar x
dnt

@mikeserv มันบอกว่าcatเกี่ยวข้องกับการสร้างไฟล์ที่ไหน? ตอบชัดเจนว่าเชลล์ทำสิ่งนี้ > fileคุณหมายถึงปัญหาอะไรกับ? ฉันมักจะใช้มันคนเดียวสำหรับตัดทอนไฟล์ที่มีอยู่ให้มีความยาวเป็นศูนย์หรือรับรองว่ามีอยู่จริง คำถามนี้เกี่ยวกับสาเหตุที่ใช้< from > toไม่ได้cat < from > toและ UUoC ไม่ใช่ "โปรดให้เหตุผลกับฉันว่าทำไมจึงcatไม่ใช่สิ่งทดแทนที่ดีสำหรับฉันcp"
Kaz

1
@dnt, tarเป็นArchiver เทป tarการใช้งานหลายอย่างยังคงทำงานกับอุปกรณ์เทปแรกโดยค่าเริ่มต้น
Stéphane Chazelas

1

< file1 > file2 ดูเหมือนว่าจะขึ้นอยู่กับเปลือกบน zsh มันใช้งานได้บนทุบตีไม่ได้

แก้ไข: ลบข้อความเท็จ


cp -aสงวนคุณลักษณะของfile1และเขียนทับคุณลักษณะของ file2 ตรงข้ามกับพฤติกรรมที่ต้องการ นอกจากนี้ฉันไม่สามารถบอกได้ด้วยการดูหน้าคนว่าจะเกิดอะไรขึ้นกับลิงก์ยาก ๆ แต่ฉันคิดว่ามันปลอดภัยที่จะบอกว่าลิงก์ถาวรของfile2จะไม่ได้รับการเก็บรักษาไว้
สัญลักษณ์ตัวแทน

ถูกต้องฉันไม่ได้อ่านคำถามนี้อย่างถี่ถ้วน
Delicioustea

1

นอกจากคำตอบที่ดีทั้งหมดแล้วคุณสามารถหลีกเลี่ยง UUOC ได้โดยจำลอง a cat:

awk 1 file1 > file2   # For line-oriented text, not binaries.
dd if=file1 of=file2  # Works for binary files, too.
# many more geeky ways.

คำสั่งเหล่านี้ไม่ได้คัดลอกข้อมูล meta ของไฟล์cpอย่างที่คิด


จริง แต่มันมูลค่าการกล่าวขวัญว่าพวกเขามีความได้เปรียบและไม่เพียง แต่ข้อเสีย (ประสิทธิภาพความน่าเชื่อถือ) catมากกว่า ที่นี่คุณต้องการคำสั่งเพื่อเลื่อนข้อมูลระหว่างตัวอธิบายไฟล์สองตัวและcatเป็นหนึ่งในตัวที่ดีที่สุดสำหรับสิ่งนั้น ดูpvสิ่งที่จะสามารถใช้splice()บน Linux สำหรับ fifos ได้ด้วย (แม้ว่ามันจะไม่fadvise(POSIX_FADV_SEQUENTIAL)เหมือนกับ GNU catก็ตาม)
Stéphane Chazelas

ddคำสั่งสำหรับไฟล์ไบนารีดูเหมือนว่าดี ... หรือจะcatทำงานได้เป็นอย่างดีสำหรับไฟล์ไบนารี?
Wildcard

@Wildcard catยังใช้งานได้กับไฟล์ไบนารี (โดยทั่วไป Unix จะไม่แยกความแตกต่างอย่างไรก็ตามเครื่องมือบางอย่างทำงานแบบบรรทัดต่อบรรทัดเช่น awk, grep, wc, ... POSIX ยังกำหนดความยาวบรรทัดที่น้อยที่สุดดังนั้นในทางทฤษฎี เครื่องมือบรรทัดที่มุ่งเน้นอาจปฏิเสธที่จะจัดการกับเส้นที่มีขนาดใหญ่มากเกินไป).
Jens

2
@ StéphaneChazelasคำตอบนี้มีวัตถุประสงค์เพื่อเป็นลิ้นในแก้ม ดูเหมือนว่าแม้จะมีฤดูกาล แต่บางคนแพ้ความสนุกสนาน (ไม่ได้กำกับที่คุณฉันให้ความสำคัญกับความเชี่ยวชาญของเชลล์และมาตรฐานการทำงานของ Opengroup)
Jens

sed '' < file1 > file2;-)
Digital Trauma

0

หากใช้งานได้อย่าแก้ไข

ฉันจะใช้

cat < file1 > file2

และไม่ทำให้เหงื่อออกจากความหมายของพีซี

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