มีสถานการณ์ที่เป็นไปได้เมื่อใด
ls -l file.txt
แสดงจำนวนไบต์ไม่เท่ากัน
wc -c file.txt
ในสคริปต์หนึ่งฉันพบว่าการเปรียบเทียบค่าทั้งสองนั้น อะไรคือเหตุผลของสิ่งนั้น? เป็นไปได้ไหมที่จะมีจำนวนไบต์ต่างกันในไฟล์เดียวกัน
มีสถานการณ์ที่เป็นไปได้เมื่อใด
ls -l file.txt
แสดงจำนวนไบต์ไม่เท่ากัน
wc -c file.txt
ในสคริปต์หนึ่งฉันพบว่าการเปรียบเทียบค่าทั้งสองนั้น อะไรคือเหตุผลของสิ่งนั้น? เป็นไปได้ไหมที่จะมีจำนวนไบต์ต่างกันในไฟล์เดียวกัน
คำตอบ:
ใช่มีกรณีดังกล่าว
ในกรณีของการsymlinksในระบบ Linux กับ GNU ls
ที่ls -l
จะทำให้ขนาดของการเชื่อมโยงในขณะที่wc -c
จะแก้ไขไฟล์จริงและอ่านจำนวนไบต์ที่มี ด้านล่างคุณจะเห็นว่าls -l
รายงาน 29 ไบต์ในขณะที่wc
รายงาน 172 ไบต์ในไฟล์จริง
$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 29 1月 17 2016 /etc/resolv.conf -> ../run/resolvconf/resolv.conf
$ wc -c /etc/resolv.conf
172 /etc/resolv.conf
$ wc -c /var/run/resolvconf/resolv.conf
172 /var/run/resolvconf/resolv.conf
$ ls -l /var/run/resolvconf/resolv.conf
-rw-r--r-- 1 root root 172 1月 15 15:49 /var/run/resolvconf/resolv.conf
ในกรณีของระบบไฟล์เสมือน , เช่น/proc
หรือ/sys
ไฟล์จำนวนมากจะมีการแสดงให้เห็นว่ามีขนาด ls -l
0 ภายใต้/dev
ระบบไฟล์เรามีไฟล์พิเศษที่หลากหลายเช่นอุปกรณ์ตัวละครและอุปกรณ์บล็อค - wc -c
แฮงค์มันและls -l
แสดงหมายเลขหลักและรองแทนขนาด
ไปป์ที่มีชื่อจะถูกรายงานเป็น0
ไบต์โดยls -c
แต่wc -c
จะอ่านเนื้อหาของไปป์ไลน์ดังนั้นในทางเทคนิคแล้วมันจะบอกคุณว่ามีข้อมูลอยู่ในไพพ์ที่มีชื่อเท่าไร:
$ mkfifo named.pipe
$ echo "This is a test" > named.pipe &
[1] 2129
$ ls -l named.pipe
prw-rw-r-- 1 xieerqi xieerqi 0 1月 16 08:40 named.pipe|
$ wc -c named.pipe
15 named.pipe
[1] + Done echo "This is a test" >named.pipe
สำหรับไฟล์ปกติขนาดควรเท่ากัน
จุดls -l
และwc -c
และวิธีการทำงานยังแตกต่างกัน wc -c
จริง ๆ แล้วเปิดไฟล์สำหรับอ่าน (คุณจะเห็นว่าถ้าคุณเรียกใช้strace wc -c /etc/passwd
ตัวอย่าง) ls -l
ทำการstat()
โทรเท่านั้น นอกจากนี้ยังอธิบายว่าทำไม/proc
ls -l
ขนาดที่แสดงถึง 0 - คุณไม่สามารถสร้างไฟล์เหล่านั้นได้เนื่องจากไฟล์เหล่านั้นไม่ใช่ "ของจริง" หรือเก็บไว้ในฮาร์ดไดรฟ์ / ssd wc -c
แทนอ่านเนื้อหาของไฟล์แทนและคำนวณขนาดไฟล์แทน
ในที่สุดls -l
เป็นเพียงเครื่องมือสำหรับการแสดงรายการแบบโต้ตอบ มันไม่ค่อยเหมาะสำหรับการเขียนสคริปต์ เมื่อคุณต้องการอ่านข้อมูลให้ใช้wc -c
แทน
โปรดทราบว่าสำหรับการเขียนสคริปต์และการประเมินขนาดของไฟล์ls
นั้นไม่ใช่ตัวเลือกที่ดีที่สุด ในความเป็นจริงมันเป็นหนึ่งในวิธีปฏิบัติร่วมกันกับหลีกเลี่ยงการแยกls
เอาท์พุท กรุณาใช้du -b
สำหรับการหาขนาดของไฟล์
/sys/
, /proc/
ฯลฯ ) อาจให้stat
ข้อมูลหากผู้ดำเนินการเลือก ส่วนใหญ่ไม่มีเหตุผลที่น่าสนใจดังนั้นจึงถูกละไว้ ตัวอย่างรวมถึง/proc/kcore
รายงานขนาดของหน่วยความจำเคอร์เนลที่กำหนดแอดเดรสได้ (โดยปกติจะมากกว่าหน่วยความจำฟิสิคัลที่มีอยู่)
ls -l
จะคืนขนาดของไฟล์ที่รายงานโดยระบบไฟล์
wc -c
จะพยายามอ่านไฟล์เพื่อกำหนดขนาด 'จริง' จากการสังเกตของฉันดูเหมือนจะพยายามค้นหาจุดจบก่อนและถ้าไม่ได้ผลมันจะอ่านไฟล์ทั้งหมดและนับขนาดตามที่ไป
นี่เป็นคำอธิบายง่ายๆเกี่ยวกับสิ่งที่เครื่องมือทั้งสองทำ แต่นำไปสู่ความเกี่ยวข้องหลายประการสำหรับผลลัพธ์:
ls
จะให้ผลลัพธ์ที่ไม่ถูกต้องสำหรับระบบไฟล์บางระบบ ตัวอย่างเช่นระบบไฟล์เสมือนจริง/proc
จะรายงานขนาดเป็นศูนย์สำหรับไฟล์จำนวนมากเนื่องจาก "ไฟล์" เหล่านี้ไม่ได้ถูกจัดเก็บในที่ใด ๆ มันถูกสร้างขึ้นตามความต้องการของซอฟต์แวร์
wc
จะไม่ทำงานเลยสำหรับไฟล์ที่ไม่มีสิทธิ์อ่านในขณะที่ls
ต้องการเฉพาะสิทธิ์ในการแสดงรายการไดเรกทอรี (เปรียบเทียบls -l /etc/shadow
กับwc -c /etc/shadow
)
ดังที่กล่าวไว้ในคำตอบอื่น ๆ พฤติกรรมของลิงก์สัญลักษณ์ก็แตกต่างกันเช่นกัน เพราะwc
พยายามที่จะอ่านมันจบลงด้วยการอ่านไฟล์ที่จุด symlink ในขณะที่เพราะls
เพียงแค่สอบถามระบบไฟล์มันจะรายงานขนาดที่ใช้ในการจัดเก็บลิงก์สัญลักษณ์เอง
ฉันแน่ใจว่ามีความแตกต่างอื่น ๆ ที่ฉันยังไม่ได้คิด แต่ฉันคิดว่าฉันจะให้คำอธิบายที่ชัดเจนและเรียบง่ายเกี่ยวกับเหตุผลพื้นฐานที่อยู่เบื้องหลังความแตกต่างเหล่านี้
seek()
สำหรับการกล่าวขวัญสิทธิ์อ่านและ นี่เป็นกรณีหลังจากเรียกใช้strace wc -l
ไฟล์ขนาดใหญ่คู่
สำหรับไฟล์ปกติ ls และ wc call stat อย่างไรก็ตามสำหรับไฟล์ของ / proc หรือ / sys ls จะคืนค่า 0 แต่ wc จะคืนค่าตัวเลขอื่น:
$ ls -l /proc/modules
-r--r--r-- 1 root root 0 Jan 16 14:56 modules
^ this one
$ wc -c /proc/modules
7621 modules
นี่อาจเป็นวิธีในการค้นหาว่าบางสิ่งบางอย่างเป็นไฟล์พิเศษ
wc -c
อย่างน้อยฉันก็โทรfstat
แต่ดูเหมือนว่าเพื่อวัตถุประสงค์อื่น มันจะค้นหาความยาวของไฟล์โดยเริ่มlseek
ต้นจนจบ ในกรณีที่ส่งคืนข้อผิดพลาดมันread
เป็นไฟล์ทั้งหมด