ความแตกต่างระหว่าง“ cat” และ“ cat <”


70

ผมทำงานผ่านการกวดวิชาและเห็นการใช้งานของทั้งสองและcat myfile.txt cat < myfile.txtมีความแตกต่างระหว่างสองคำสั่งเหล่านี้หรือไม่? ดูเหมือนว่าทั้งคู่จะพิมพ์เนื้อหาของไฟล์ลงในเชลล์


คำตอบ:


106

ในกรณีแรกให้catเปิดไฟล์และในกรณีที่สองเชลล์จะเปิดไฟล์โดยส่งผ่านเป็นcatอินพุตมาตรฐาน

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

นั่นไม่ใช่สถานการณ์ปกติ แต่บอกว่าชี้ให้เห็นว่าเชลล์และcatไม่ใช่โปรแกรมเดียวกัน


83
sudo cat myfile.txtใช่และตัวอย่างเช่นคุณสามารถทำได้ แต่sudo cat < myfile.txtจะไม่ทำงานหากคุณไม่มีสิทธิ์ในการอ่านไฟล์
zuazo

2
โปรดทราบว่าksh93มีcatbuiltin (ไม่ได้เปิดใช้งานโดยค่าเริ่มต้นเว้นแต่คุณจะมี/opt/ast/binในช่วงต้นของคุณ$PATHแม้ว่า)
Stéphane Chazelas

2
บางโปรแกรมทำงานแตกต่างกันไปขึ้นอยู่กับว่าพวกเขาได้รับอาร์กิวเมนต์ชื่อไฟล์หรือ stdin ตัวอย่างเช่นwcจะพิมพ์ชื่อไฟล์ก่อนการนับเมื่อได้รับการโต้แย้ง
Barmar

21

ไม่มีความแตกต่างที่เห็นได้ชัดเจนในกรณีทดสอบของคุณ สิ่งที่ชัดเจนที่สุดคือข้อความแสดงข้อผิดพลาดที่คุณได้รับหากไม่มีชื่อไฟล์myfile.txtในไดเรกทอรีปัจจุบันหรือหากคุณไม่ได้รับอนุญาตให้อ่าน

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

$ cat myfile.txt
cat: myfile.txt: No such file or directory
$ cat < myfile.txt
ksh93: myfile.txt: cannot open [No such file or directory]

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

$ echo one > one
$ echo two > two
$ cat one two # cat opens one, shows one, opens two, shows two
one
two
$ cat < one < two # sh opens one then opens two, cat shows stdin (two)
two
$ rm one two
$ echo one > one
$ cat one two # cat opens and shows one, fails to open two
one
cat: two: No such file or directory
$ cat < one < two # the shell opens one then opens two, fails and 
                  # displays an error message, cat gets nothing on stdin
                  # so shows nothing
ksh93: two: cannot open [No such file or directory]

บนระบบมาตรฐานเชลล์และcatไม่มีความแตกต่างในสิทธิ์การเข้าถึงไฟล์ดังนั้นทั้งสองจะประสบความสำเร็จในการล้มเหลวอย่างเท่าเทียมกัน การใช้sudoเพื่อยกระดับcatสิทธิ์ของผู้ใช้จะสร้างความแตกต่างอย่างมากในการทำงานตามที่ Thomas Dickey ตอบและแสดงความคิดเห็นที่แนบมาแล้ว


5
จากความอยากรู้จริงๆคุณใช้การใช้งานkshจากความตั้งใจของคุณเองและถ้าเป็นเช่นนั้น ... ทำไม ?
แมว

1
@cat - คำถามนั้นตั้งอยู่บนพื้นฐานของความไม่รู้ สร้างมันเองและดู
mikeserv

2
@ mikeserv ที่ตั้งใจจะ flippant ไม่หยาบคายอย่างจริงจัง แต่ก็ยุติธรรมพอฉันคิดว่า
cat

2
@cat - ฉันไม่คิดอย่างนั้น ความไม่รู้ไม่ใช่สิ่งที่น่าละอาย - เป็นเพียงการขาดความรู้ หากคุณไม่เข้าใจว่าทำไมบางคนอาจเลือกที่จะใช้ ksh93 ดังนั้นฉันจะถือว่ามันเป็นเพราะคุณไม่เคยใช้มัน ดังนั้นฉันขอแนะนำให้คุณทำ มันคุ้มค่าที่จะลองเพื่อให้แน่ใจ และเชื่อฉันเมื่อฉันบอกคุณว่าเมื่อเทียบกับbash, ksh93อยู่ไกลออกไปเปลือกที่ดีกว่า มันเป็นเปลือกเกือบ
mikeserv

5
ในฐานะที่เป็น @mikeserv ชี้ให้เห็นที่อื่น , cat < file1 > file2มีผลแตกต่างจากcat file1 > file2ในกรณีที่file1ไม่สามารถอ่านได้หรือไม่มี (แบบฟอร์มหลังถูกตัดทอนโดยfile2ที่อดีตจะไม่ตัด)
Wildcard

7

cat myfile.txtอ่านไฟล์myfile.txtจากนั้นพิมพ์ไฟล์ไปยังเอาต์พุตมาตรฐาน

cat < myfile.txtที่นี่catไม่ได้รับไฟล์ใด ๆ ที่จะเปิดดังนั้นคำสั่ง Unix ที่เหมือนกันจะอ่านข้อมูลจากอินพุตมาตรฐานซึ่งส่งตรงจากfile.txtเชลล์และพิมพ์ไปยังเอาต์พุตมาตรฐาน


6

@Thomas Dickeyคำตอบนั้นยอดเยี่ยม

ฉันแค่ต้องการเพิ่มข้อเท็จจริงที่ชัดเจนเกี่ยวกับกรณีที่อ่านไฟล์หลายไฟล์ (เกี่ยวข้องกับคำถามของคุณอย่างหลวม ๆ แต่ก็ยัง):

  • cat <file1 <file2 <file3จะอ่านเฉพาะไฟล์ 3 อย่างน้อยก็เป็น bash (อันที่จริงมันขึ้นอยู่กับเชลล์ แต่เชลล์ส่วนใหญ่จะทำซ้ำทุกไฟล์ที่ระบุเป็น stdin ซึ่งทำให้ไฟล์ล่าสุดมีผล)
  • cat file1 file2 file3จะอ่านไฟล์ทั้งหมดที่ระบุตามลำดับ (อันที่จริงcatเป็นรูปแบบย่อของคำต่อกัน )
  • cat file1 file2 file3 <file4 <file5 <file6 จะอ่านเฉพาะ file1, file2, file3 (เนื่องจาก cat ละเว้น stdin เมื่ออาร์กิวเมนต์ของชื่อไฟล์ถูกส่งผ่าน)
    • cat file1 file2 - file3 <file4 <file5 <file6 จะอ่าน file1, file2, file6, file3 (เนื่องจากยัติภังค์บังคับให้แมวไม่ต้องสนใจ stdin)

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


1
โปรดทราบว่าในตัวอย่างแรกของคุณcatจะยังคงเปิดfile1และfile2เหมือนกันกับfile4และfile5ในตัวอย่างที่สามของคุณ มันจะแสดงเฉพาะการตอบfile3สนอง file6เนื้อหาถ้าคำแนะนำการเปิดก่อนหน้านี้ประสบความสำเร็จ
jlliagre

@jlliagre ขอบคุณฉันไม่รู้ เห็นได้ชัดว่า Strace พิสูจน์ความถูกต้องของคุณ ฉันแก้ไขข้อความในวงเล็บสำหรับกรณีที่ 1 และ 3a
sasha

0

เราสามารถใช้คำสั่งอื่นเพื่อสังเกตเห็นความแตกต่างระหว่าง:

wc –w food2.txt .

เอาต์พุตที่เป็นไปได้:

6 food2.txt .

คำสั่งจะบอกชื่อไฟล์เนื่องจากมันรู้จัก (ผ่านเป็นอาร์กิวเมนต์)

wc –w < food2.txt .

เอาต์พุตที่เป็นไปได้:

6 .

อินพุตมาตรฐานถูกเปลี่ยนเส้นทางไปยังไฟล์ food2.txt โดยไม่ต้องมีคำสั่งรู้

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