Windows filepath ถูกแปลงเป็น Linux filepath


13

ฉันมีเส้นทาง Windows ในตัวแปรทุบตีเป็นสตริง:

file='C:\Users\abcd\Downloads\testingFile.log'

/c/Users...ฉันพยายามที่จะแปลงเส้นทางนี้เข้ามาในเส้นทางลินุกซ์ที่เริ่มต้นด้วย

ความพยายามของฉัน

ผลงานดังต่อไปนี้:

file=${file/C://c}
file=${file//\\//}
echo $file
> /c/Users/abcd/Downloads/testingFile.log

ปัญหา

ที่นี่ฉันได้ทำสิ่งนี้สำหรับสตริงที่มี filepath เหตุผลที่ฉันถามคำถามนี้คือฉันต้องแปลง 20 สตริงดังกล่าวในสคริปต์ทุบตีใน Ubuntu 16.04 และทุกครั้งที่ฉันทำเช่นนี้ฉันต้องเขียน 2 บรรทัดต่อการแปลง - มันใช้พื้นที่มาก!

คำถาม

มีวิธีรวม 2 คำสั่งหรือไม่

file=${file/C://c}
file=${file//\\//}

เป็นคำสั่งเดียว?


1
ใช้สำหรับห่วง (และอาจจะเป็นอาร์เรย์) พูดตัวแปรของคุณด้วย
wjandrea

ขอบคุณ คุณสามารถแสดงตัวอย่างของวิธีการทำเช่นนี้ในวงหรืออาร์เรย์?
edesz

คำตอบ:


17

จะมีวิธีในการทำทั้งสองอย่างในคราวเดียวsedแต่ก็ไม่จำเป็น

นี่คือวิธีที่ฉันจะแก้ปัญหานี้:

  1. ใส่ชื่อไฟล์ในอาร์เรย์
  2. ทำซ้ำอาร์เรย์

filenames=(
  'C:\Users\abcd\Downloads\testingFile.log'
  # ... add more here ...
)

for f in "${filenames[@]}"; do
  f="${f/C://c}"
  f="${f//\\//}"
  echo "$f"
done

หากคุณต้องการใส่ผลลัพธ์ลงในอาร์เรย์แทนที่จะพิมพ์ให้แทนที่echoบรรทัดด้วยการกำหนด:

  filenames_out+=( "$f" )

ตกลง แต่ถ้าฉันมี 2 ไฟล์f1และf2มันจะทำงานอย่างไร ฉันหมายถึงฉันจะกำหนดชื่อไฟล์ใหม่ให้กับอาร์เรย์ได้อย่างไรโดยแทนที่ชื่อเก่า
edesz

@WR ใส่ em ใน array ใหม่และใช้สิ่งนั้น
muru

@WR เพิ่มเข้าไปในคำตอบ
wjandrea

1
ฉันขอแนะนำให้สร้างอาร์เรย์ใหม่เพื่อความชัดเจน
wjandrea

9

หากเป็นสิ่งที่คุณต้องการทำหลายครั้งทำไมไม่สร้างฟังก์ชั่นเชลล์ขึ้นมา

win2lin () { f="${1/C://c}"; printf '%s\n' "${f//\\//}"; }

$ file='C:\Users\abcd\Downloads\testingFile.log'
$ win2lin "$file"
/c/Users/abcd/Downloads/testingFile.log
$ 
$ file='C:\Users\pqrs\Documents\foobar'
$ win2lin "$file"
/c/Users/pqrs/Documents/foobar

นั่นไม่ใช่ความคิดที่เลว แต่ก็ดูเหมือนจะไม่ให้/c/Users...- C:\Users\...แทนจะให้
edesz

@WR apologies - ข้อผิดพลาดการคัดลอกวาง โปรดลองตอนนี้
รถเหล็ก

1
ขอบคุณฉันใช้cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }ในระบบย่อย Windows สำหรับ Linux ทำงานได้ดีมาก!
สุดสัปดาห์

2

คุณจะสามารถบรรลุสิ่งนี้ในหนึ่งบรรทัดโดยใช้ sed

file="$(echo "$file" | sed -r -e 's|^C:|/c|' -e 's|\\|/|g')"

โปรดสังเกตว่าทั้งสองรูปแบบจะต้องแยกจากกันอย่างไรก็ตามการแข่งขันจะถูกแทนที่ด้วยการเปลี่ยนตัวที่แตกต่างกัน


1
คำพ้องความหมาย:file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
wjandrea

1

คำถามนี้ยังเปิดรับข้อเสนอแนะใหม่หรือไม่ ถ้าเป็นเช่นนี้สิ่งนี้จะช่วยคุณได้ไหม?

$ file="/$(echo 'C:\Users\abcd\Downloads\testingFile.log'|tr '\\' '/')"
$ echo $file
/C:/Users/abcd/Downloads/testingFile.log

โอ้และในกรณีที่ต้องโยน C เป็นตัวพิมพ์เล็ก:

file="/$(echo 'C:\Users\abcd\Downloads\testingFile.log'|tr '^C' 'c'|tr '\\' '/')"

ในฐานะที่เป็นภาพรวม:

$ file='C:\Users\abcd\Downloads\testingFile.log'
$ echo $file
C:\Users\abcd\Downloads\testingFile.log
$ file="/$(echo $file|tr '^C' 'c'|tr '\\' '/')"
$ echo $file
/c:/Users/abcd/Downloads/testingFile.log

เหตุผลในการใช้'^C'คืออะไร?
edesz

1
^ หมายถึงจุดเริ่มต้นของบรรทัดมิฉะนั้นการเกิดขึ้นของ C ทั้งหมดจะกลายเป็นตัวพิมพ์เล็ก ... หากมีผู้ใช้

ฉันต้องเพิ่มว่าข้อเสนอแนะอื่น ๆ ยังใช้งานได้ คำสั่ง Unix จำนวนมากสามารถทำงานเดียวกันดังนั้นจึงขึ้นอยู่กับคุณว่ารูปแบบการแก้ปัญหาที่คุณต้องการใช้

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