ผมทำงานผ่านการกวดวิชาและเห็นการใช้งานของทั้งสองและcat myfile.txt
cat < myfile.txt
มีความแตกต่างระหว่างสองคำสั่งเหล่านี้หรือไม่? ดูเหมือนว่าทั้งคู่จะพิมพ์เนื้อหาของไฟล์ลงในเชลล์
ผมทำงานผ่านการกวดวิชาและเห็นการใช้งานของทั้งสองและcat myfile.txt
cat < myfile.txt
มีความแตกต่างระหว่างสองคำสั่งเหล่านี้หรือไม่? ดูเหมือนว่าทั้งคู่จะพิมพ์เนื้อหาของไฟล์ลงในเชลล์
คำตอบ:
ในกรณีแรกให้cat
เปิดไฟล์และในกรณีที่สองเชลล์จะเปิดไฟล์โดยส่งผ่านเป็นcat
อินพุตมาตรฐาน
ในทางเทคนิคแล้วพวกเขาอาจมีผลกระทบที่แตกต่างกัน ตัวอย่างเช่นมันเป็นไปได้ที่จะมีการใช้งานเชลล์ที่มีสิทธิพิเศษ (หรือน้อยกว่า) มากกว่าcat
โปรแกรม สำหรับสถานการณ์สมมติที่หนึ่งอาจล้มเหลวในการเปิดไฟล์ในขณะที่อื่น ๆ ได้
นั่นไม่ใช่สถานการณ์ปกติ แต่บอกว่าชี้ให้เห็นว่าเชลล์และcat
ไม่ใช่โปรแกรมเดียวกัน
sudo cat myfile.txt
ใช่และตัวอย่างเช่นคุณสามารถทำได้ แต่sudo cat < myfile.txt
จะไม่ทำงานหากคุณไม่มีสิทธิ์ในการอ่านไฟล์
ksh93
มีcat
builtin (ไม่ได้เปิดใช้งานโดยค่าเริ่มต้นเว้นแต่คุณจะมี/opt/ast/bin
ในช่วงต้นของคุณ$PATH
แม้ว่า)
wc
จะพิมพ์ชื่อไฟล์ก่อนการนับเมื่อได้รับการโต้แย้ง
ไม่มีความแตกต่างที่เห็นได้ชัดเจนในกรณีทดสอบของคุณ สิ่งที่ชัดเจนที่สุดคือข้อความแสดงข้อผิดพลาดที่คุณได้รับหากไม่มีชื่อไฟล์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 ตอบและแสดงความคิดเห็นที่แนบมาแล้ว
ksh
จากความตั้งใจของคุณเองและถ้าเป็นเช่นนั้น ... ทำไม ?
bash
, ksh93
อยู่ไกลออกไปเปลือกที่ดีกว่า มันเป็นเปลือกเกือบ
cat myfile.txt
อ่านไฟล์myfile.txt
จากนั้นพิมพ์ไฟล์ไปยังเอาต์พุตมาตรฐาน
cat < myfile.txt
ที่นี่cat
ไม่ได้รับไฟล์ใด ๆ ที่จะเปิดดังนั้นคำสั่ง Unix ที่เหมือนกันจะอ่านข้อมูลจากอินพุตมาตรฐานซึ่งส่งตรงจากfile.txt
เชลล์และพิมพ์ไปยังเอาต์พุตมาตรฐาน
@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 จริง ๆ ) ในทั้งสองกรณีรหัสทางออกที่ผิดพลาดจะถูกส่งคืน
cat
จะยังคงเปิดfile1
และfile2
เหมือนกันกับfile4
และfile5
ในตัวอย่างที่สามของคุณ มันจะแสดงเฉพาะการตอบfile3
สนอง file6
เนื้อหาถ้าคำแนะนำการเปิดก่อนหน้านี้ประสบความสำเร็จ
เราสามารถใช้คำสั่งอื่นเพื่อสังเกตเห็นความแตกต่างระหว่าง:
wc –w food2.txt
.
เอาต์พุตที่เป็นไปได้:
6 food2.txt
.
คำสั่งจะบอกชื่อไฟล์เนื่องจากมันรู้จัก (ผ่านเป็นอาร์กิวเมนต์)
wc –w < food2.txt
.
เอาต์พุตที่เป็นไปได้:
6
.
อินพุตมาตรฐานถูกเปลี่ยนเส้นทางไปยังไฟล์ food2.txt โดยไม่ต้องมีคำสั่งรู้