Windows filepath chuyển đổi sang filepath Linux


13

Tôi có một đường dẫn Windows trong một biến bash dưới dạng một chuỗi:

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

Tôi đang cố gắng chuyển đổi đường dẫn này thành đường dẫn Linux bắt đầu bằng /c/Users....

Nỗ lực của tôi

Các công việc sau đây:

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

Vấn đề

Ở đây, tôi đã thực hiện điều này cho một chuỗi có chứa filepath. Lý do tôi đặt câu hỏi này là tôi phải chuyển đổi 20 chuỗi như vậy trong tập lệnh bash trong Ubuntu 16.04 và mỗi lần tôi làm điều này, tôi phải viết 2 dòng trên mỗi chuyển đổi - nó chiếm rất nhiều dung lượng!

Câu hỏi

Có cách nào để kết hợp 2 lệnh không

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

vào một lệnh?


1
Sử dụng một vòng lặp for (và có thể là một mảng). Cũng trích dẫn các biến của bạn.
wjandrea

Cảm ơn. Bạn có thể chỉ ra một ví dụ về cách làm điều này trong một vòng lặp hoặc mảng không?
edesz

Câu trả lời:


17

Sẽ có một cách để thực hiện cả hai thay thế cùng một lúc bằng cách sử dụng sed, nhưng không cần thiết.

Đây là cách tôi sẽ giải quyết vấn đề này:

  1. Đặt tên tệp trong mảng
  2. Lặp lại trên mảng

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

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

Nếu bạn muốn đặt đầu ra thành một mảng thay vì in, hãy thay thế echodòng bằng một phép gán:

  filenames_out+=( "$f" )

Ok.Nhưng nếu tôi có 2 tập tin f1f2nó sẽ hoạt động như thế nào? Ý tôi là, làm thế nào để tôi gán lại tên tệp mới cho mảng bằng cách thay thế tên cũ?
edesz

@WR đặt em vào một mảng mới và sử dụng nó.
muru

@WR Đã thêm vào câu trả lời
wjandrea

1
Tôi khuyên bạn nên tạo một mảng mới, vì sự rõ ràng.
wjandrea

9

Nếu đó là điều bạn muốn làm nhiều lần, vậy thì tại sao không tạo một hàm shell nhỏ?

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

Đó không phải là một ý tưởng tồi. Tuy nhiên, nó dường như không cho /c/Users...- thay vào đó là cho C:\Users\....
edesz

@WR xin lỗi - lỗi sao chép-dán. Hãy thử nó ngay bây giờ.
Steeldo

1
Cảm ơn, tôi sử dụng cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }trong hệ thống con Windows cho Linux, hoạt động như một cơ duyên!
Cuối tuần

2

Bạn sẽ có thể đạt được điều này trong một dòng bằng cách sử dụng sed

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

Lưu ý rằng hai mẫu phải được tách riêng dù sao vì các trận đấu được thay thế bằng các thay thế khác nhau.


1
Từ đồng nghĩa:file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
wjandrea

1

Là câu hỏi này vẫn mở cho các đề xuất mới? Nếu vậy, điều này sẽ giúp bạn?

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

Ồ, và trong trường hợp chữ C phải được viết thành chữ thường:

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

Như một tổng quan:

$ 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

Lý do của việc sử dụng là '^C'gì?
edesz

1
^ có nghĩa là bắt đầu dòng, nếu không, tất cả các lần xuất hiện của C sẽ trở thành chữ thường ... nếu có

Tôi phải thêm rằng các đề xuất khác cũng hoạt động. Nhiều lệnh Unix có thể thực hiện cùng một công việc, do đó tùy thuộc vào kiểu giải pháp bạn thích sử dụng.

Tôi đã không hỏi trước đó về ^điều đó đã được sử dụng trong một số câu trả lời khác ở đây quá. Cảm ơn câu trả lời và lời giải thích.
edesz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.