มีสถานการณ์ที่เป็นไปได้เมื่อใด
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 -l0 ภายใต้/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เป็นไฟล์ทั้งหมด