เหตุใด 'ls' จึงตัดรายการด้วยช่องว่างในเครื่องหมายคำพูดเดี่ยว


187

ฉันเพิ่งสังเกตเห็นว่าในหนึ่งในเครื่องของฉัน (เรียกใช้ Debian Sid) เมื่อใดก็ตามที่ฉันพิมพ์lsชื่อไฟล์ใด ๆ ที่มีช่องว่างมีคำพูดเดียวรอบมัน

ฉันตรวจสอบชื่อแทนของฉันทันทีเพื่อค้นหาพวกเขาเหมือนเดิม

wyatt@debian630:~/testdir$ ls
'test 1.txt'  test1.txt
wyatt@debian630:~/testdir$ alias
alias ls='ls --color=auto'
alias wget='wget --content-disposition'
wyatt@debian630:~/testdir$

(ภาพ)

การทดสอบอื่นด้วยไฟล์ที่มีเครื่องหมายคำพูดเดี่ยวในชื่อของพวกเขา (เช่นการตอบคำขอโดย jimmij):

wyatt@debian630:~/testdir$ ls
'test 1.txt'  test1.txt  'thishasasinglequotehere'\''.txt'
wyatt@debian630:~/testdir$ touch "'test 1.txt'"
wyatt@debian630:~/testdir$ ls
''\''test 1.txt'\'''  test1.txt
'test 1.txt'          'thishasasinglequotehere'\''.txt'

(ภาพ)

อัพเดตด้วยเอาต์พุต coreutils-8.26 ใหม่ (ซึ่งเป็นที่ยอมรับน้อยกว่าความสับสน แต่ยังคงเกิดการระคายเคืองตามค่าเริ่มต้น) ขอบคุณPádraig Brady สำหรับงานพิมพ์นี้:

$ ls
"'test 1.txt'"   test1.txt
'test 1.txt'    "thishasasinglequotehere'.txt"

$ ls -N
'test 1.txt'  test1.txt
test 1.txt    thishasasinglequotehere'.txt

ทำไมสิ่งนี้จึงเกิดขึ้น ฉันจะหยุดมันอย่างถูกต้องได้อย่างไร

เพื่อชี้แจงฉันเองตั้ง ls เอาท์พุทสีโดยอัตโนมัติ มันไม่เคยใส่เครื่องหมายคำพูดรอบ ๆ สิ่งต่าง ๆ มาก่อน

ฉันวิ่งbashแล้ว coreutils 8.25

แก้ไข: ปรากฏว่านักพัฒนา coreutils คิดว่า(ลิงก์)มันจะเป็นความคิดที่ดีที่จะทำให้มันเป็นค่าเริ่มต้นของโลกแม้ว่าจะทำลายหลักการของความประหลาดใจอย่างน้อยที่สุดรวมถึงประเพณี UNIX 46 ปีขึ้นไป

วิธีใดในการแก้ไขโดยไม่ต้องคอมไพล์ใหม่?


อัปเดต - ตุลาคม 2017 - Debian Sid ได้เปิดใช้งานการอ้างอิงเชลล์ใหม่อีกครั้งโดยค่าเริ่มต้น นี่เป็นเพียงการไร้สาระ https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=877582

และที่ด้านล่างของห่วงโซ่การตอบกลับไปยังรายงานข้อผิดพลาดก่อนหน้านี้ "การเปลี่ยนแปลงนั้นตั้งใจและจะยังคงอยู่" https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=813164#226

ฉันคิดว่านี่ถูกตัดสิน ชัดเจนว่าไม่.

ปรับปรุง: เมษายน 2019: เพิ่งพบรายงานข้อผิดพลาดที่ยิ่งใหญ่ใน PHP ที่เกิดจากการเปลี่ยนแปลงlsนี้ เมื่อคุณสร้างความสับสนให้กับนักพัฒนาและสร้างรายงานข้อผิดพลาดที่ผิดพลาดถึงเวลาแล้วที่จะต้องคิดถึงการเปลี่ยนแปลงของคุณอีกครั้ง

อัปเดต: กล่องของเล่น Android lsกำลังทำสิ่งที่คล้ายกัน แต่มีแบ็กสแลชแทนที่จะเป็นเครื่องหมายคำพูด การใช้ตัวเลือก -q ทำให้ช่องว่างแสดงผลเป็น 'อักขระเครื่องหมายคำถาม' (ฉันไม่ได้ตรวจสอบสิ่งที่พวกเขาเป็นเพราะเห็นได้ชัดว่าไม่ได้มีช่องว่าง) ดังนั้นการแก้ไขเดียวที่ฉันพบจนถึงขณะนี้โดยไม่ต้องรูทอุปกรณ์ที่สงสัย นี่คือสคริปต์และแหล่งที่มามันเมื่อเปิดตัวเปลือก ฟังก์ชั่นนี้lsใช้คอลัมน์ถ้าอยู่ในเทอร์มินัลและพิมพ์หนึ่งรายการต่อบรรทัดในขณะที่หลอกให้lsพิมพ์คำต่อคำในช่องว่างเพราะมันวิ่งผ่านไปป์

ls() {
    # only way I can stop ls from escaping with backslashes
    if [ -t 1 ]; then
        /system/bin/ls -C "$@" |cat
    else
        /system/bin/ls "$@" |cat
    fi
}

20
อีกเหตุผลหนึ่งที่ทำไมไม่แยกวิเคราะห์lsคำสั่ง
jimmij

12
มันดูแปลก ๆ แต่ถ้ามันเปิดใช้งานเฉพาะเมื่อพิมพ์ไปยังเครื่องเทอร์มินัล คุณสามารถเห็นได้อย่างชัดเจนว่าคุณมีไฟล์ 'ทดสอบ 1.txt' แทนที่จะเป็นไฟล์ 'ทดสอบ' และอีก '1.txt' ลองls | catดูว่ามันหายไปไหม หากฉันมีเครื่องย้อนเวลาฉันจะกลับไปที่ Bell Labs ~ 1970 และพยายามโน้มน้าวให้ Ken Thompson ให้พื้นที่ในชื่อไฟล์และไดเรกทอรีเป็นความคิดที่ไม่ดี :-P
Bjorn Munch

6
ครั้งแรกที่ผมเห็นนี้ผม freaked '*'ออกคิดว่าหนึ่งในสคริปต์ของฉันได้ไปเป๋และเปลี่ยนชื่อไฟล์ทั้งหมดของฉันไป ฉันเดาว่าฉันจะเพิ่มlsชื่อแทนไปยังเครื่องจักรทั้งหมดของฉันเพื่อกำจัดมัน ...
จำกัด

14
@LimitedAtonement ตามที่แหลมโดยLekensteynคุณสามารถทำได้ด้วยตัวแปรสภาพแวดล้อมQUOTING_STYLE=literalแทนที่จะเป็นนามแฝง (ฉันเดาว่ามันเป็นเรื่องของรสนิยม แต่ฉันชอบตัวแปร)
LSpice

4
@BjornMunch มีสองวิธีในการแก้ปัญหาในการบอกว่ามันเป็นหนึ่งไฟล์หรือสอง: 1) มองหาวิธีการวาดคอลัมน์และมันค่อนข้างชัดเจน 2) รายการหนึ่งรายการต่อบรรทัด ทั้งคู่ดูดีกว่าและชัดเจนกว่า mangling ด้วยคำพูดเดียว
Wyatt8740

คำตอบ:


132

คำนำ : แม้ว่าอาจจะค่อนข้างพอใจที่จะตอบคำถามเช่นนี้และเรียกมันว่าวัน แต่โปรดมั่นใจได้ว่านักพัฒนา GNU ไม่สนใจเกี่ยวกับคำตอบของการโหวตดังนั้น & หากคุณต้องการกระตุ้นให้พวกเขาเปลี่ยนคุณต้องส่งอีเมลถึงพวกเขาตามคำตอบนี้


" ทำไมสิ่งนี้จึงเกิดขึ้น? "

นักพัฒนา coreutils หลายคนตัดสินใจว่าพวกเขารู้ดีกว่าหลายทศวรรษของมาตรฐานพฤตินัย


" ฉันจะหยุดมันได้อย่างไร "

http://www.gnu.org/software/coreutils/coreutils.html :

รายงานบั๊ก

หากคุณคิดว่าคุณพบข้อผิดพลาดใน Coreutils แล้วโปรดส่งรายงานข้อบกพร่องให้เสร็จสิ้นโดยสมบูรณ์ไปที่<bug-coreutils@gnu.org>และมันจะถูกป้อนเข้าสู่ตัวติดตามข้อผิดพลาด Coreutils โดยอัตโนมัติ ก่อนที่จะรายงานข้อบกพร่องโปรดอ่านคำถามที่พบบ่อย คู่มือที่มีประโยชน์และอ้างอิงบ่อยเกี่ยวกับวิธีการเขียนรายงานข้อผิดพลาดและถามคำถามที่ดีคือเอกสารวิธีการถามคำถามอย่างชาญฉลาด คุณสามารถเรียกดูการโพสต์ก่อนหน้าและค้นหาบั๊กหลัก -ututils

Distros ที่เปลี่ยนกลับ  การเปลี่ยนแปลงนี้แล้ว:

Distros ไม่ได้รับผลกระทบ:

  • openSUSE (ใช้แล้ว -N)

"มีวิธีแก้ไขปัญหานี้อย่างไรหากไม่มีคอมไพล์ซ้ำ "

ผู้เสนอจะมีคุณ ...

กลับไปที่รูปแบบเก่าโดยเพิ่ม -N ไปยัง als alias ของพวกเขา

... ในทุกการติดตั้งของคุณทุกที่ทุกเวลาตลอดไป


17
การเปลี่ยนแปลงดังกล่าวได้ถูกเสนอในรายชื่อผู้รับจดหมายและเห็นชอบโดยผู้ดูแลระบบหลักสามรายเพื่อให้ได้รับประโยชน์สุทธิ เราเปิดรับทุกข้อโต้แย้งที่สร้างสรรค์เกี่ยวกับเรื่องนี้ นี่คือโอเพ่นซอร์สหลังจากทั้งหมดเราไม่ได้ตั้งใจที่จะกำหนดเพียงเพื่อปรับปรุงสิ่งต่าง ๆ โปรดตอบกลับในเธรด coreutils ที่lists.gnu.org/archive/html/coreutils/2016-02/msg00000.html (BTW วิธีมีข้อเสนอแนะเชิงสร้างสรรค์ในการปรับปรุงข้อบกพร่องด้านสุนทรียภาพที่กล่าวถึงที่นี่ โดยการเพิ่มช่องว่างเพื่อปรับปรุงการจัดตำแหน่ง)
Pádraig Brady

31
@ PádraigBradyคำตอบที่อัปเดตแล้ว แม้ว่าจะเห็นการปฏิเสธจำนวนมากในเธรด coreutils ของคุณ บรรทัดล่างคือคุณกำลังสร้างงานมากขึ้นสำหรับคนและคุณทำมันในชื่อของระบบปฏิบัติการที่เป็นโคลนของระบบปฏิบัติการจากปี 1970 หากคนต้องการสิ่งที่แตกต่างพวกเขาจะเลือกใช้มัน
Jan Kyu Peblik

43
@ PádraigBradyการเปลี่ยนแปลงนี้ทำให้ฉันรำคาญและเสียเวลาหลายชั่วโมงในการพยายามหาสาเหตุและวิธีแก้ไข ฉันไม่ได้ตั้งใจจะลบ - ฉันแค่แบ่งปันมุมมองของคนอื่น! การปรับเปลี่ยนพฤติกรรมหลักมีผลกระทบอย่างมาก ..
มาเฟีย

52
ในฐานะที่เป็นคนที่ใช้ระบบ * nix เป็นเวลา 30 ปีฉันพบว่าการเปลี่ยนแปลงแบบฟรีนั้นน่ารำคาญมาก พวกเขาทำลายสคริปต์อันยาวนานสำหรับสิ่งหนึ่ง พวกเขายังละเมิดหลักการแห่งความประหลาดใจอย่างน้อยที่สุด "การเข้าร่วม" ควรเป็นค่าเริ่มต้นที่นี่ตามที่ระบุไว้ข้างต้น
Brian Clapper

28
@ PádraigBradyยังไม่มีวิธีที่จะผลักดันการเปลี่ยนแปลงดังกล่าว มันเป็นวิธีที่สร้างสรรค์มากขึ้นในการเลือกใช้พฤติกรรมนั้นแทนที่จะเปิดใช้งานตามค่าเริ่มต้น นอกจากนี้ยังบอกใบ้เท็จว่านี่คือวิธีจัดเก็บชื่อไฟล์ในระยะสั้นกับlsสิ่งที่คุณเห็นไม่ได้เป็นวิธีการจัดเก็บ คุณสมบัตินั้นควรเป็นทางเลือกไม่ใช่ค่าเริ่มต้น

91

คุณสามารถเลือกรูปแบบการอ้างอิง :

ls --quoting-style=literal

เหมือนกับ:

ls -N

หรือ:

QUOTING_STYLE=literal ls

ทำให้เป็นนามแฝงหรือตั้งค่าให้export QUOTING_STYLE=literalคุณ.bashrcทำพฤติกรรมล่วงหน้าได้ 8.25


11
ดูเหมือนว่าแปลกฉันต้องทำเช่นนั้นเพื่อให้ได้พฤติกรรม unix-y ปกติ นอกจากนี้ฉันต้องการค่าเริ่มต้นเก่า ฉันไม่คิดว่าการหลบหนีเป็นค่าเริ่มต้นเก่า - ฉันคิดว่ามันพิมพ์ออกมาอย่างแท้จริงว่ามีอะไรอยู่ที่นั่น
Wyatt8740

9
สำหรับพฤติกรรมก่อน 8.25 ให้ใช้export QUOTING_STYLE=literalใน bashrc ของคุณ
Lekensteyn

2
หรือใช้-Nดูเหมือนว่า ฉันแค่รวบรวมเวอร์ชั่นของฉันเองเพราะฉันได้ตั้งค่าพื้นที่เก็บข้อมูลส่วนตัวแล้ว
Wyatt8740

2
@LSpice ฉันได้แก้ไขโพสต์เพื่อใช้literalแทนescape(ฉันเชื่อว่า @cuonglm แค่ต้องการแสดงวิธีการเปลี่ยนสไตล์ไม่ใช่การกำหนดเป้าหมายเฉพาะescapeสไตล์)
Lekensteyn

5
คำตอบนี้สมควรได้รับการโหวตมากขึ้น มันตรงกับสิ่งที่ผู้ถามถามหลีกเลี่ยงคำตอบของระบบราชการ อันที่จริงวิธีการตัวแปรสภาพแวดล้อมดูเหมือนว่าสวยหรู (โดยส่วนตัวแล้วฉันชอบพฤติกรรมใหม่เพราะชอบการกระทำ C&P ที่มีประสิทธิภาพมากกว่า) แต่ ls ฉลาดพอที่จะทำตัวแบบเก่าเมื่อใช้การเปลี่ยนเส้นทางดังนั้นจึงไม่เป็นอันตรายต่อสคริปต์ที่ใช้เอาต์พุตของ ls
Marcelo

42

จุดน้อยเกี่ยวกับการเปลี่ยนแปลง

  • มันถูกนำมาใช้ใน coreutils v8.25 และการจัดตำแหน่งที่ดีขึ้นใน v8.26
  • มันจะเกิดขึ้นเฉพาะเมื่อส่งออกไปยังเทอร์มินัลดังนั้นจึงไม่ทำให้สคริปต์แตก
  • มันจะแก้ปัญหาเอาต์พุตสำหรับผู้ใช้สำหรับไฟล์ที่มีช่องว่าง
  • มัน sanitizes เอาท์พุทจึงปลอดภัยในการคัดลอกและวาง
  • ตอนนี้เอาต์พุตสามารถใช้เพื่อคัดลอกและวางกลับสู่เชลล์ได้เสมอ
  • ผู้ใช้สามารถกลับไปใช้รูปแบบเก่าได้โดยเพิ่ม -N ไปยังนามแฝง ls

7
ตัวอย่างสุดท้ายของฉันไม่ชัดเจน? อาจไม่ใช่ - แต่มันอาจทำให้สับสนและต้องใช้เวลาในการถอดรหัสมากขึ้น ฉันคิดว่ามันเป็นการเปลี่ยนแปลงที่น่ากลัว (ไม่มีความผิดสำหรับคุณ) ขอบคุณสำหรับเคล็ดลับนามแฝงว่า
Wyatt8740

27
หมายเหตุ: การเปลี่ยนแปลงนี้ถูกนำมาใช้ใน coreutils 8.25 ( กระทำเขียนโดยPádraigเช่นเดียวกับโพสต์นี้) โดยส่วนตัวแล้วฉันคิดว่าพฤติกรรมนี้เป็นสิ่งที่ไม่ดีมันหยุดการจัดตำแหน่งเมื่อใดก็ตามที่มีพื้นที่ว่างในชื่อไฟล์
Lekensteyn

10
คำขอโทษของฉัน - เห็นได้ชัดว่าคุณกำลังเปลือกอย่างปลอดภัยอ้างถึงเชลล์คำพูดอย่างน้อย ฉันยังคงไม่ชอบมัน ตัวเลือกนั้นดี - แต่การปรับเปลี่ยนพฤติกรรมเริ่มต้นที่ระบุไว้อย่างดีของยูทิลิตีแกนยูนิกซ์ที่มีอายุเก่าแก่หลายสิบปีในลักษณะที่ทำให้ความจริงลดน้อยลงเป็นความคิดที่ไม่ดีเท่านั้น
mikeserv

12
@ PádraigBradyงั้นคุณจะlsหักรึเปล่า? ดูข้อโต้แย้งเหล่านั้นทั้งหมดกับการเปลี่ยนแปลงของคุณ ไม่มีใครต้องการมัน อาจถึงเวลาที่จะขอโทษต่อโลกและยกเลิกมัน
Chris Warrick

6
@ PádraigBradyดังนั้นถึงแม้จะมีคนมากมายที่อธิบายว่ามันผิด, แตกหัก, ฯลฯ คุณยังจะไม่เปลี่ยนสิ่งนี้เพื่อให้ค่าเริ่มต้นไม่เปลี่ยนแปลง? ขัดกับความเชื่อของการเปลี่ยนแปลงนี้สร้างความสับสนไม่ disambiguates แนะนำให้ผู้คนตั้งค่าตัวแปรสภาพแวดล้อมหรือนามแฝงคือ asinine อย่างดีที่สุด
ทำเครื่องหมาย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.