เพิ่มบรรทัดใหม่ในชื่อไฟล์ด้วย `mv`


11

มันเป็นคำถามที่จริงจัง ฉันทดสอบบางawkสคริปต์และฉันต้องการไฟล์ที่มีบรรทัดใหม่ในชื่อของพวกเขา


เป็นไปได้หรือไม่ที่จะเพิ่มบรรทัดใหม่ในชื่อไฟล์ด้วยmv?

ตอนนี้ฉันสามารถทำได้ด้วยtouch:

touch "foo
bar"

ด้วยการสัมผัสฉันเพิ่มอักขระบรรทัดใหม่ต่อสำเนาและวาง แต่ฉันไม่สามารถเขียนfooReturnbarในเปลือกของฉัน

ฉันจะเปลี่ยนชื่อไฟล์เพื่อให้มีการขึ้นบรรทัดใหม่ในชื่อไฟล์ได้อย่างไร


แก้ไข 2015/06/28; 07:08 น

หากต้องการเพิ่มบรรทัดใหม่ในzshฉันสามารถใช้Alt+Return


2
คุณถามทำไม? คุณทำเรื่องตลกหรือหลอกเพื่อน?
Basile Starynkevitch

2
อย่าลบคำถามมันมีประโยชน์ แต่หลีกเลี่ยงบรรทัดใหม่ในชื่อไฟล์ให้มากที่สุด
Basile Starynkevitch

2
อะไรที่ทำให้คุณคิดว่าการทำมันmvจะแตกต่างจากการทำด้วยtouch? คุณลองแบบเดียวกันหรือเปล่า?
เควิน

2
ดีที่คุณสามารถคัดลอกและวางลงในคำสั่งได้อย่างง่ายดายเพียงเป็นmv touch
Kevin

2
ดังนั้นฉันขอแนะนำให้คุณกำหนด OP ของคุณให้ชัดเจนยิ่งขึ้น: ภายในสภาพแวดล้อมเชลล์ที่กำหนดฉันไม่สามารถพิมพ์บรรทัดใหม่ภายในสตริงที่ยกมาเช่นเดียวกับใน echo "a [return] b"
แดน

คำตอบ:


22

เป็นความคิดที่ดี (มีตัวอักษรแปลก ๆ ในชื่อไฟล์) แต่คุณสามารถทำได้

 mv somefile.txt "foo
 bar"

(คุณสามารถทำได้mv somefile.txt "$(printf "foo\nbar")"หรือmv somefile.txt foo$'\n'barอื่น ๆ ... รายละเอียดเฉพาะกับเชลล์ของคุณฉันใช้zsh)

อ่านเพิ่มเติมเกี่ยวกับglobbingเช่นglob (7) รายละเอียดอาจเป็นแบบเฉพาะเชลล์ แต่เข้าใจว่า/bin/mv ได้รับ (โดยเชลล์ของคุณ), ผ่านexecve (2) , อาเรย์ที่ขยายตัวของข้อโต้แย้ง: การขยายข้อโต้แย้งและกลมกลืนเป็นความรับผิดชอบของเชลล์ที่กล่าวอ้าง

และคุณสามารถรหัสโปรแกรม C ขนาดเล็กเพื่อทำสิ่งเดียวกัน:

#include <stdio.h>
#include <stdlib.h>
int main() {
  if (rename ("somefile.txt", "foo\nbar")) {
     perror("rename somefile.txt");
     exit(EXIT_FAILURE);
  };
  return 0;
}

บันทึกโปรแกรมข้างต้นในfoo.cคอมไพล์gcc -Wall foo.c -o foo แล้วรัน./foo

ในทำนองเดียวกันคุณสามารถเขียนโค้ดสคริปต์ที่คล้ายกันใน Perl, Ruby, Python, Ocaml, ฯลฯ ....

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

ที่จริงแล้วฉันยังแนะนำให้ใช้เฉพาะตัวอักษรตัวเลขและ+-/._% อักขระที่ไม่เน้นเสียง(โดย/ เป็นตัวคั่นไดเรกทอรี) ในเส้นทางของไฟล์ .ควรใช้ไฟล์ "ซ่อน" (เริ่มต้นด้วย) ด้วยความระมัดระวังและ parcimony ฉันเชื่อว่าการใช้พื้นที่ใด ๆ ในชื่อไฟล์เป็นความผิดพลาด ใช้ขีดล่างแทน (เช่นfoo/bar_bee1.txt) หรือลบ (เช่นfoo/bar-bee1.txt)


ใช่ฉันรู้ว่าฉันสามารถคัดลอกและวางอักขระบรรทัดใหม่ได้ แต่ฉันจะทำอย่างไรโดยไม่คัดลอกและวาง
AB

4
ไม่มีการคัดลอกหรือวางที่นี่ มีการขึ้นบรรทัดใหม่ที่พิมพ์หลังจากfooนั้น
แดน

อย่างไรก็ตามมันยังใช้งานได้ก็อปปี้แล้ววาง
kos

1
มันเป็นความคิดที่ดีสำหรับไฟล์ปกติ แต่เป็นกรณีทดสอบที่ดีอย่างที่ OP อธิบาย
artdanil

5
@และ,จะเป็นอันตรายมากกว่า-(เหมือนในตำแหน่งแรก) %หรือ การแนะนำทั้งหมดเหล่านี้ส่วนใหญ่จะแก้ไขข้อผิดพลาดในบางแอปพลิเคชัน รู้สึกย้อนกลับที่จะให้ผู้คนไม่ใช้ตัวละครเหล่านั้นแทนที่จะแก้ไขข้อบกพร่องของพวกเขา
Stéphane Chazelas

19

หากคุณใช้ bash คำสั่งนี้จะทำงาน

mv a $'b\nc'

4
ทำงานร่วมกับzsh=)
AB

3
bash เช่น zsh และ FreeBSD sh คัดลอกมาจาก ksh93
Stéphane Chazelas

ขอบคุณมาก! ฉันลืมเกี่ยวกับ $ ใน bash โดยสิ้นเชิงในขณะที่มันเป็นคำตอบของฉันเองเกี่ยวกับ SO แนะนำให้ใช้ - stackoverflow.com/questions/1825552/grep-a-tab-in-unix/…
antimirov

6

ฉันรู้ว่าคุณขอmvวิธีแก้ปัญหาอย่างไรก็ตามแม้จะมีคำเตือนก็สามารถทำได้อย่างง่ายดายด้วยrename(ในแพ็คเกจ Perl):

~/tmp$ touch foo
~/tmp$ rename 's/$/\nbar/' foo
Unsuccessful stat on filename containing newline at /usr/share/perl5/File/Rename.pm line 69.
~/tmp$ ls
foo?bar

ขอบคุณสำหรับrenameความคิดที่ดีมาก +1
AB

5

แง่มุมหนึ่งของปัญหานี้ไม่ได้เกี่ยวกับawk- และเพียงเล็กน้อยเกี่ยวกับเชลล์ ปัญหาคือโดยทั่วไปแล้ววินัยของ tty ของเคอร์เนลจะทำการบัฟเฟอร์อินพุตของคุณ - เพียงแค่สะท้อนไปที่หน้าจอของคุณ

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

ดังนั้นเพื่อความสะดวกสิ่งที่คุณต้องการคือวิธีส่ง\newline ไปยังเทอร์มินัลบัฟเฟอร์โดยไม่ต้องดันอินพุตอื่นทั้งหมดทันที วิธีมาตรฐานในการทำเช่นนั้นคือ w / ลำดับของคีย์CTRL+V- ซึ่งเป็นเครื่องหมายคำพูดสำหรับเทอร์มินัลอักขระอินพุตถัดไปของคุณ ทำเช่นCTRL+Vนั้นCTRL+J- เพราะหลังมักเป็นวิธีพิมพ์\newline ตัวอักษร คุณจะรู้ว่ามันใช้งานได้เมื่อคุณไม่เห็น$PS2เพราะเชลล์ยังไม่ได้อ่านอินพุตของคุณ

หมายเหตุแม้ว่าว่าเมื่อมันไม่อ่านที่ป้อนข้อมูลของคุณก่อนหน้านี้CTRL+Vจะได้ทำให้ความแตกต่างสำหรับเปลือกที่ทุกคนไม่มี - ที่คำพูดเพียง แต่สำหรับสายวินัย คุณจะต้องเสนอราคาขึ้นบรรทัดใหม่และทำทุกอย่างที่มีความหมาย

โดยวิธีการที่CTRL+Vสามารถนำไปใช้ประโยชน์ในรูปแบบอื่น ๆ - ตัวอย่าง"$(printf \\33)"ไม่ได้เป็นวิธีเดียวที่จะเขียนESCตัวอักษรลงในเปลือกสคริปต์ - และมันไม่ได้ง่ายที่สุด คุณสามารถป้อนอักขระใด ๆ ที่แป้นพิมพ์ของคุณจะส่งโดยไม่ต้องใช้ไดรเวอร์อินพุตพยายามแปลมันหากคุณเพิ่งหลบหนีด้วยวิธีนี้

ฉันมักจะชอบใช้ <tab> บนบรรทัดคำสั่งโดยไม่มีเชลล์พยายามทำอะไรให้เสร็จ เพราะโดยทั่วไปเชลล์ที่ทำเสร็จแล้วจะกำหนดค่า <tab> ในลักษณะที่มีความหมายเหมือนกันstty eol \tเพื่อให้ระบบเสร็จสมบูรณ์นั้นCTRL+Vทำงานได้สำหรับฉันแม้ในสภาพแวดล้อมที่ไม่คุ้นเคย


2
ขอบคุณที่พูดถึง 'Ctrl + V' ฉันกำลังจะโพสต์คำตอบเกี่ยวกับมันแล้วเห็นคำอธิบายของคุณ
artdanil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.