Làm cách nào tôi có thể sử dụng ký tự đại diện kiểu ms-dos với ls và mv?


9

Tôi gặp điều không may khi đến từ nền tảng MS-DOS - nhưng ít nhất nó khiến tôi đánh giá cao Linux mạnh hơn bao nhiêu. Tôi đã làm việc để đưa Linux-Fu của mình ngang hàng, nhưng có một vài điều có thể được thực hiện với DOS mà tôi không chắc làm thế nào để thực hiện dễ dàng nhất với Linux:

Đổi tên nhiều tệp - Sử dụng hai ký tự đại diện

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\>rename *.txt *.bak

c:\> dir

Directory of c:\
    file1.bak
    file2.bak
    file3.bak
    file4.bak

Tôi biết tôi có thể sử dụng find -execở đây nhưng có thể sử dụng cú pháp ngắn hơn - có thể mvvới một số cờ hoặc cú pháp đặc biệt? Tôi đoán chìa khóa của cái này là ký tự đại diện thứ hai * vì linux không có vấn đề gì với cái thứ nhất (tức là tôi biết cách chọn các tệp tôi muốn đổi tên bằng cách sử dụng ký tự đại diện)

Đổi tên một tệp - Sử dụng một ký tự đại diện

c:\> dir

Directory of c:\
    file1.txt

c:\>rename file1.txt *.bak

c:\> dir

Directory of c:\
    file1.bak

Điều này sẽ đặc biệt hữu ích khi đổi tên tên tệp dài và khó sử dụng. Tôi nghĩ có lẽ tôi có thể sử dụng mv file1.txt $1.bakđể kết thúc với file1.txt.bakđiều đó cũng có thể chấp nhận được nhưng tôi không chắc bạn có thể tham chiếu một $1tham số nội tuyến bằng lệnh shell. Một lần nữa, trong trường hợp cụ thể này, thật tiện lợi khi ms-dos bastardized *ký tự đại diện được sử dụng như một kiểu bắt / thay thế khớp cho một phần của tên tệp.

Lọc danh sách thư mục bằng ký tự đại diện

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt
    text.txt
    \temp       (directory) 

c:\> dir file*

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\> t*

Directory of c:\
    text.txt
    \temp       (directory) 

Tôi không chắc cú pháp đúng để làm điều đó lslà gì, hoặc nếu nó thậm chí có thể. Nếu tôi đã làm một cái gì đó như ls t*nó sẽ tái diễn vào các thư mục bắt đầu với t. Cách giải quyết của tôi đã được sử dụng find . --max-depth 1 -iname "t*"hoặc một cái gì đó tương tự ls -al | grep t- không phải cái nào cũng ngắn và đơn giản như vậy dir t*.

Cuối cùng, tôi biết rằng tôi có thể thiết lập các bí danh để làm cho các lệnh dài này ngắn hơn, nhưng tôi muốn tìm hiểu một số linux-fu ngoài luồng để thực hiện những việc này vì đôi khi bạn được kết nối với hệ thống từ xa hoặc làm việc trên một máy mới.

Vậy làm thế nào tôi có thể mvlscác tệp giống như cách tôi đã sử dụng dirrenamecác tệp?

Câu trả lời:


15

Một trong những khác biệt cơ bản giữa hệ cmdvỏ Windows và POSIX là người chịu trách nhiệm mở rộng ký tự đại diện. Shell thực hiện tất cả các mở rộng cần thiết trước khi bắt đầu các lệnh thực tế mà bạn yêu cầu. cmd chủ yếu chuyển các mẫu ký tự đại diện cho các lệnh không được sửa đổi. (Tôi nói chủ yếu, vì tôi nghĩ rằng có ngoại lệ và các biến môi trường được mở rộng trong hầu hết các trường hợp.) Điều này làm cho việc viết một renamecái sẽ hoạt động với cùng một cú pháp như trong cmdkhá khó khăn.

Nhưng có một renamephiên bản dành cho Linux - với các đối số hoàn toàn khác nhau, hãy kiểm tra trang man (một chút ngắn gọn trên hệ thống của tôi và renamexuất phát từ util-linuxgói trên hệ thống của tôi, có sẵn rộng rãi). Đổi tên đầu tiên của bạn sẽ được thực hiện như thế này:

rename .txt .bak *.txt

Lưu ý rằng shell thực hiện việc *mở rộng, vì vậy renamebản thân nó thực sự nghĩ rằng nó đã được gọi như thế này:

rename .txt .bak file1.txt file2.txt file3.txt ...

Vì vậy, bạn có thể đoán phiên bản tập tin duy nhất:

rename .txt .bak file1.txt

Nếu bạn không muốn sử dụng renamenhưng tự thực hiện điều này, bạn có thể tạo một chức năng cho việc đó. Giả sử bạn chỉ muốn thay đổi phần mở rộng tệp và để đổi tên tệp đơn, hãy xem điều này:

$ function chext() {
  newext="$1"
  file="$2"
  newfile="${file%.*}$newext"
  echo mv "$file" "$newfile"
}
$ chext .csv test.txt
mv text.txt text.csv

$newfileđược xây dựng bằng cách sử dụng loại bỏ chuỗi con để loại bỏ phần mở rộng ban đầu, sau đó nối phần mở rộng mới. Bạn có thể mở rộng chức năng đó để xử lý nhiều tệp tương đối dễ dàng.


Đối với lscâu hỏi của bạn , sử dụng -dchuyển đổi. Điều này sẽ ngăn chặn việc lsliệt kê nội dung của các thư mục.

Bản giới thiệu:

$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:29 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.csv
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Đổi tên ký tự đại diện

$ rename .csv .txt f*
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Đổi tên tập tin đơn

$ rename .txt .csv f1.txt 
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Mặc định ls

$ ls -l t*
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

test:
total 0
-rw-r--r-- 1 owner users 0 Jan  7 17:33 dont_show_me_please

ls mà không kiểm tra thư mục

$ ls -ld t*
drwxr-xr-x 2 owner users 4096 Jan  7 17:33 test
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

rất đẹp! Tôi nghĩ rằng tôi vừa mới chuyển lên một vành đai với linux-fu của tôi! cảm ơn!
cwd

Mẹo để tiến bộ một chút với điều này (và tránh những cạm bẫy): sử dụng các hàm hoặc tập lệnh đơn giản để xem điều gì sẽ xảy ra khi bạn làm điều đó somefunc *.Extnếu mẫu đó không khớp với bất kỳ tệp nào và chơi với trích dẫn để xem liệu bạn có quản lý để vượt qua một mẫu không ( mà không có nó mở rộng) giữa các chức năng. Mẹo an toàn: không sử dụng rmbất cứ nơi nào trong khi thử nghiệm mở rộng toàn cầu / vỏ :-)
Mat

4

Một điều cần lưu ý khi nói đến ký tự đại diện là chúng được mở rộng bằng vỏ. Ứng dụng không biết liệu bạn đã sử dụng ký tự đại diện hay gõ tên. Ví dụ, nếu bạn gõ rename *.txt *.bak, thì renamelệnh sẽ thấy một cái gì đó như rename file1.txt file2.txt existingfile.bak. Đó là không đủ thông tin để tiếp tục.

Tôi sẽ giải quyết câu hỏi về lsđầu tiên, bởi vì nó đơn giản hơn. Nếu tất cả những gì bạn muốn là tên phù hợp, thì bạn không cần ls, vì shell đã thực hiện việc mở rộng.

echo t*

Nếu bạn muốn biết thêm thông tin về các tập tin, sau đó chuyển -dtùy chọn sang ls, để bảo nó không liệt kê nội dung của các thư mục.

ls -ld t*

Không có tiện ích tiêu chuẩn để đổi tên tệp, vì các hệ thống unix đầu tiên không đi kèm với một. Phương thức di động để đổi tên tệp sử dụng một vòng lặp và hơi dài dòng:

for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done

Có một số tiện ích phổ biến để đổi tên các tệp, không có tiện ích nào được đảm bảo cài đặt trên một hệ thống unix nhất định, nhưng tất cả đều dễ cài đặt. Đây là những cái chính:

  • renametừ util-linuxbộ phần mềm, có sẵn trên mọi hệ thống Linux không nhúng (và không ở đâu khác). Trên Debian và các dẫn xuất (bao gồm Ubuntu), lệnh này được gọi rename.ul. Với điều kiện là không có sự xuất hiện nào .txtkhác ngoài phần mở rộng cuối cùng, bạn có thể viết

    rename .txt .bak *.txt
    
  • renamelà tập lệnh Perl mà Debian và các dẫn xuất gửi /usr/bin/rename. Bạn có thể đổi tên các tệp theo các lệnh Perl tùy ý.

    rename 's/\.txt\z/\.bak/' *.txt
    
  • mmv, có thể đổi tên, sao chép và liên kết các tệp theo một số mẫu dựa trên tên và có nhiều tùy chọn liên quan đến những gì xảy ra nếu tên đích đã tồn tại. Lưu ý rằng bạn phải sử dụng dấu ngoặc kép để bảo vệ ký tự đại diện khỏi sự mở rộng của trình bao.

    mmv '*.txt' '#1.txt'
    
  • zmvlà một hàm zsh , có sẵn khi và chỉ khi vỏ của bạn là zsh. Nó có thể khớp các mẫu zsh tùy ý (vì vậy bạn có thể khớp tên tệp theo các biểu thức chính quy tùy ý, không chỉ các ký tự đại diện và bạn có thể khớp các tệp theo các tiêu chí khác như ngày và kích thước). zmvcũng có thể sao chép và liên kết.

    zmv '(*).txt' '$1.txt'
    

Nếu bạn có một số quyền kiểm soát đối với các máy bạn sử dụng, khuyến nghị của tôi là sử dụng zsh làm vỏ của bạn (nó có lợi ích khác so với bash) và đặt các dòng này vào ~/.zshrc:

autoload -U zmv
alias zmv='noglob zmv -w'
alias zcp='zmv -C'
alias zln='zmv -L'
alias zsy='zmv -Ls'

nogloblà một tính năng zsh bảo shell không mở rộng các ký tự đại diện trong đối số của lệnh. Bằng cách này bạn có thể viết zmv *.txt \$1.txt(bạn sẽ luôn cần bảo vệ $văn bản thay thế).

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.