อะไรคือความแตกต่างระหว่าง“ du -sh *” และ“ du -sh ./*”?


26

ความแตกต่างระหว่างdu -sh *และdu -sh ./*คืออะไร

หมายเหตุ: สิ่งที่ฉันสนใจคือ*และ./*ชิ้นส่วน


2
ผลลัพธ์ ? จะมีการแสดง. / ต่อหน้าชื่อไฟล์
Kiwy

คำตอบ:


69
$ touch ./-c $ 'a \ n12 \ tb' foo
$ du -hs *
0 ก
12 b
0 foo
0 ทั้งหมด

อย่างที่คุณเห็น-cไฟล์ถูกใช้เป็นตัวเลือกduและไม่ถูกรายงาน (และคุณเห็นtotalบรรทัดเนื่องจากdu -c) นอกจากนี้ไฟล์ที่เรียกว่าa\n12\tbจะทำให้เราคิดว่ามีไฟล์ที่เรียกว่าและab

$ du -hs -- *
0       a
12      b
0       -c
0       foo

นั่นดีกว่า. อย่างน้อยคราว-cนี้ไม่ได้เป็นตัวเลือก

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

นั่นดีกว่า ./ป้องกันคำนำหน้า-cจากการถูกนำมาเป็นตัวเลือกและกรณีที่ไม่มี./มาก่อนbในการส่งออกบ่งชี้ว่าไม่มีbไฟล์ในนั้น แต่มีไฟล์ที่มีตัวอักษรขึ้นบรรทัดใหม่ ( แต่ดูด้านล่าง1สำหรับ digressions เพิ่มเติมเกี่ยวกับที่)

มันเป็นวิธีที่ดีที่จะใช้./คำนำหน้าเมื่อเป็นไปได้และหากไม่ได้และข้อมูลโดยพลการที่คุณควรเสมอใช้:

cmd -- "$var"

หรือ:

cmd -- $patterns

หากcmdไม่รองรับ--การทำเครื่องหมายจุดสิ้นสุดของตัวเลือกคุณควรรายงานว่าเป็นข้อผิดพลาดต่อผู้เขียน (ยกเว้นเมื่อมีตัวเลือกและจัดทำเอกสารเช่นecho)

มีหลายกรณีที่./*แก้ปัญหาที่--ไม่เป็น ตัวอย่างเช่น

awk -f file.awk -- *

ล้มเหลวหากมีไฟล์ที่เรียกว่าa=b.txtในไดเรกทอรีปัจจุบัน (ตั้งค่าตัวแปร awk aเป็นb.txtแทนที่จะบอกให้ประมวลผลไฟล์)

awk -f file.awk ./*

ไม่มีปัญหาเนื่องจาก./aไม่ใช่ชื่อตัวแปร awk ที่ถูกต้องดังนั้นจึง./a=b.txtไม่ถือเป็นการกำหนดตัวแปร

cat -- * | wc -l

ล้มเหลวหากมีไฟล์ที่เรียกว่า-ในไดเรกทอรีปัจจุบันตามที่บอกcatให้อ่านจาก stdin ( -เป็นพิเศษกับยูทิลิตี้การประมวลผลข้อความส่วนใหญ่และถึงcd/ pushd)

cat ./* | wc -l

เป็นเพราะตกลงไม่ได้เป็นพิเศษเพื่อ./-cat

สิ่งที่ชอบ:

grep -l -- foo *.txt | wc -l

เพื่อนับจำนวนไฟล์ที่มีfooผิดเนื่องจากถือว่าชื่อไฟล์ไม่มีอักขระขึ้นบรรทัดใหม่ ( wc -lนับอักขระขึ้นบรรทัดใหม่เอาต์พุตเหล่านั้นโดยgrepสำหรับแต่ละไฟล์และไฟล์ในชื่อไฟล์เอง) คุณควรใช้แทน:

grep -l foo ./*.txt | grep -c /

(การนับจำนวน/ตัวอักษรมีความน่าเชื่อถือมากกว่าเนื่องจากมีเพียงหนึ่งชื่อไฟล์เท่านั้น)

สำหรับการเรียกซ้ำgrepจะใช้กลอุบายที่เทียบเท่ากัน:

grep -rl foo .//. | grep -c //

./* อาจมีผลข้างเคียงที่ไม่พึงประสงค์

cat ./*

เพิ่มอักขระอีกสองตัวต่อไฟล์ดังนั้นจะทำให้คุณมีขนาดถึงขีด จำกัด สูงสุดของข้อโต้แย้ง + สภาพแวดล้อมในไม่ช้า และบางครั้งคุณไม่ต้องการ./ให้มีการรายงานในผลลัพธ์ ชอบ:

grep foo ./*

จะส่งออก:

./a.txt: foobar

แทน:

a.txt: foobar

พูดนอกเรื่องต่อไป

1 . ฉันรู้สึกว่าฉันต้องขยายที่นี่ตามการอภิปรายในความคิดเห็น

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

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

สิ่งที่หมายถึงคือการส่งออกของdu ./*ซึ่งตรงกันข้ามกับของdu -- *) สามารถแยกได้อย่างน่าเชื่อถือแม้ว่าจะไม่ได้อย่างง่ายดายในสคริปต์

เมื่อเอาต์พุตไปยังเทอร์มินัลมีหลายวิธีที่ชื่อไฟล์อาจหลอกคุณ:

  • อักขระควบคุมลำดับการหลีกเลี่ยงอาจส่งผลต่อวิธีการแสดงผลของสิ่งต่าง ๆ ตัวอย่างเช่น\rเลื่อนเคอร์เซอร์ไปที่จุดเริ่มต้นของบรรทัด\bเลื่อนเคอร์เซอร์กลับ\e[Cไปข้างหน้า (ในเทอร์มินัลส่วนใหญ่) ...
  • อักขระจำนวนมากมองไม่เห็นบนเทอร์มินัลโดยเริ่มจากตัวอักษรที่ชัดเจนที่สุด: อักขระเว้นวรรค
  • มีอักขระ Unicode ที่มีลักษณะเหมือนกับเครื่องหมายทับในแบบอักษรส่วนใหญ่

    $ printf '\u002f \u2044 \u2215 \u2571 \u29F8\n'
    /    

    (ดูว่ามันทำงานอย่างไรในเบราว์เซอร์ของคุณ)

ตัวอย่าง:

$ touch x 'x ' $'y\bx' $'x\n0\t.\u2215x' $'y\r0\t.\e[Cx'
$ ln x y
$ du -hs ./*
0       ./x
0       ./x
0       ./x
0       .∕x
0       ./x
0       ./x

มีจำนวนมากxแต่yขาดหายไป

เครื่องมือบางอย่างเช่นGNUls จะแทนที่อักขระที่ไม่สามารถพิมพ์ได้ด้วยเครื่องหมายคำถาม (โปรดทราบว่า(U + 2215) สามารถพิมพ์ได้) เมื่อเอาต์พุตไปที่เทอร์มินัล GNU duทำไม่ได้

มีวิธีที่จะทำให้พวกเขาเปิดเผยตัวเอง:

$ ls
x  x   x?0?.∕x  y  y?0?.?[Cx  y?x
$ LC_ALL=C ls
x  x?0?.???x  x   y  y?x  y?0?.?[Cx

ดูวิธีการหันไป???หลังจากที่เราบอกlsว่าชุดตัวละครของเราเป็น ASCII

$ du -hs ./* | LC_ALL=C sed -n l
0\t./x$
0\t./x $
0\t./x$
0\t.\342\210\225x$
0\t./y\r0\t.\033[Cx$
0\t./y\bx$

$ทำเครื่องหมายจุดสิ้นสุดของบรรทัดดังนั้นเราจึงสามารถมองเห็น"x"vs "x ", อักขระที่ไม่สามารถพิมพ์ได้และอักขระที่ไม่ใช่ ASCII ทั้งหมดแสดงด้วยเครื่องหมายแบ็กสแลช (แบ็กสแลชเองจะถูกแสดงด้วยเครื่องหมายแบ็กสแลชสองตัว) นั่นคือ GNU sedมันควรจะเหมือนกันในทุกsedการใช้งานที่เป็นไปตาม POSIX แต่โปรดทราบว่าsedการใช้งานแบบเก่าบางอย่างไม่เป็นประโยชน์

$ du -hs ./* | cat -vte
0^I./x$
0^I./x $
0^I./x$
0^I.M-bM-^HM-^Ux$

(ไม่ใช่แบบมาตรฐาน แต่ค่อนข้างธรรมดาและcat -Aมีการใช้งานบางอย่าง) อันนั้นมีประโยชน์และใช้การเป็นตัวแทนที่แตกต่างกัน แต่ไม่ชัดเจน ( "^I"และ<TAB>จะแสดงเช่นเดียวกัน)

$ du -hs ./* | od -vtc
0000000   0  \t   .   /   x  \n   0  \t   .   /   x      \n   0  \t   .
0000020   /   x  \n   0  \t   . 342 210 225   x  \n   0  \t   .   /   y
0000040  \r   0  \t   . 033   [   C   x  \n   0  \t   .   /   y  \b   x
0000060  \n
0000061

อันนั้นเป็นมาตรฐานและไม่คลุมเครือ (และสอดคล้องกันจากการนำไปใช้กับการนำไปใช้) แต่ไม่ง่ายที่จะอ่าน

คุณจะสังเกตเห็นว่าyไม่เคยปรากฏขึ้นด้านบน นั่นเป็นปัญหาที่ไม่เกี่ยวข้องอย่างสมบูรณ์กับdu -hs *สิ่งที่ไม่เกี่ยวข้องกับชื่อไฟล์ แต่ควรจดบันทึก: เนื่องจากduรายงานการใช้งานดิสก์มันจะไม่รายงานลิงก์อื่น ๆ ไปยังไฟล์ที่แสดงรายการอยู่แล้ว ( duการใช้งานไม่ได้ทั้งหมดจะมีพฤติกรรมเช่นนั้น บนบรรทัดคำสั่ง)


+1, ดีและทั่วถึง (เท่าที่ฉันบอกได้ ^^) ฉันชอบข้อดีของ "grep -c /" เป็นพิเศษ นอกจากนี้ยังมีข้อควรระวัง: ข้อได้เปรียบของ "./*" มากกว่า "*" ปรากฏอยู่ในหนึ่งในคำตอบที่ดีของคำถามที่พบบ่อยเกี่ยวกับ Unix (อาจเป็น faqs.org iirc เป็นคำถามเกี่ยวกับไฟล์ rm-ing ที่เริ่มต้นด้วย a "-")
Olivier Dulac

…และไม่ใช่วิธีที่ดีที่จะมีไฟล์ที่มีการขึ้นบรรทัดใหม่และแท็บในชื่อใช่หรือไม่ ฉันรู้ว่าฉันพยายามที่จะชื่อ [a-z0-9.+-]จำกัด
แบล็กไลท์ส่องแสง

5
@BlacklightShining มันแย่มากที่จะขโมยรถ แต่มันก็ไม่ดีที่จะปลดล็อครถของคุณ (ไม่ต้องขึ้นบรรทัดใหม่) โดยเฉพาะอย่างยิ่งเมื่อเป็นรถราคาแพง (สคริปต์ทำงานในฐานะผู้ใช้ที่มีสิทธิพิเศษบนเซิร์ฟเวอร์ที่มีข้อมูลสำคัญ ... ) จอดไว้ในพื้นที่ขรุขระ ( /tmp) หรือพื้นที่ที่มีรถยนต์ราคาแพงจำนวนมาก ( $HOME) และยิ่งแย่ไปกว่านั้นถ้าคุณไปที่ไซต์ถาม - ตอบและบอกว่าไม่เป็นไรที่จะล็อครถของคุณโดยไม่ต้องระบุเงื่อนไขใด ๆ คุณเขียนทำงานด้วยตัวเองเพียงบนเครื่องไม่ได้เชื่อมต่อกับเครือข่ายใด ๆ หรือการเก็บข้อมูลแบบถอด ... )
Stéphane Chazelas

1
@ BlacklackShining บรรทัดใหม่เป็นเรื่องแปลก แต่พื้นที่ฝังตัวเป็นเรื่องธรรมดาในปัจจุบันโดยเฉพาะอย่างยิ่งสำหรับไฟล์ที่สร้างผ่าน GUI
alexis

2
@BlacklightShining ใช่ว่าที่หนึ่ง (เช่น"b "หรือ"a\bb") จะหลอกผู้ใช้บนขั้ว du ./*แต่ไม่สคริปต์แยกการส่งออกของ ฉันควรจะเพิ่มบันทึกเกี่ยวกับเรื่องนั้น จะทำในวันพรุ่งนี้ โปรดทราบว่าก่อนหน้านี้ฉันหมายถึงเอกสิทธิ์ในความหมายทั่วไปไม่ใช่root(แม้ว่าจะใช้กับทุกอย่างมากขึ้นrootแน่นอน) อนุญาตให้ขึ้นบรรทัดใหม่ได้โดยไม่สนใจว่าเป็นข้อบกพร่อง ข้อบกพร่องมีนิสัยที่ถูกเอาเปรียบ คุณต้องวัดความเสี่ยงเป็นราย ๆ ไป การฝึกการเขียนโปรแกรมที่ดีสามารถหลีกเลี่ยงปัญหาในหลาย ๆ กรณี แน่นอนเกี่ยวกับ SE เราควรสร้างความตระหนัก
Stéphane Chazelas

6

ไม่มีความแตกต่างระหว่าง a *และ./*ในแง่ของสิ่งที่ไฟล์จะแสดงรายการ ความแตกต่างเพียงอย่างเดียวคือในรูปแบบที่ 2 แต่ละไฟล์จะมีจุดทับ./ด้านหน้านำหน้าซึ่งโดยทั่วไปหมายถึงไดเรกทอรีปัจจุบัน

จำไว้ว่า.ไดเรกทอรีนั้นเป็นรูปแบบย่อของไดเรกทอรีปัจจุบัน

$ ls -la | head -4
total 28864
drwx------. 104 saml saml    12288 Jan 23 20:04 .
drwxr-xr-x.   4 root root     4096 Jul  8  2013 ..
-rw-rw-r--.   1 saml saml      972 Oct  6 20:26 abcdefg

คุณสามารถโน้มน้าวใจตัวเองว่า 2 รายการเหล่านี้เป็นสิ่งเดียวกันโดยใช้echoเพื่อดูว่าเชลล์จะขยายไปยังอะไร

$ echo *
$ echo ./*

คำสั่ง 2 เหล่านี้จะแสดงรายการไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันของคุณ

ตัวอย่าง

เราสามารถสร้างข้อมูลปลอมบางอย่างเช่น:

$ touch file{1..5}
$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file1
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file2
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file3
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file4
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file5

ตอนนี้เมื่อเราใช้echoคำสั่งข้างต้นเราจะเห็นผลลัพธ์ต่อไปนี้:

$ echo *
file1 file2 file3 file4 file5
$ echo ./*
./file1 ./file2 ./file3 ./file4 ./file5

ความแตกต่างนี้อาจดูไม่จำเป็น แต่ก็มีหลายสถานการณ์ที่คุณต้องการรับประกันให้กับเครื่องมือบรรทัดคำสั่ง Unix ต่างๆที่คุณส่งชื่อไฟล์ผ่านทางบรรทัดคำสั่งและไม่มีอะไรเพิ่มเติม!

ดังนั้นทำไมจึงใช้. / *

เมื่อคำตอบของ @ Stephane ชี้ให้เห็นเนื่องจากลักษณะของอักขระที่ถูกกฎหมายเมื่อตั้งชื่อไฟล์และไดเรกทอรีใน Unix ชื่อไฟล์ที่เป็นอันตรายสามารถสร้างขึ้นได้ซึ่งมีผลข้างเคียงที่ไม่คาดคิดเมื่อพวกมันถูกส่งไปยังคำสั่ง Unix ต่างๆ

บ่อยครั้งที่การใช้งาน./จะถูกใช้เพื่อช่วยรับประกันว่าชื่อไฟล์ที่ขยายจะถือว่าเป็นชื่อไฟล์เมื่อส่งผ่านเป็นอาร์กิวเมนต์ไปยังคำสั่ง Unix ต่างๆ

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