Làm cách nào để thực hiện các lệnh trong thư mục khác mà không lặp lại đường dẫn thư mục?


73

Có một cách thông minh để thực hiện sao chép và di chuyển các hoạt động hoặc một lệnh để sao chép một tập tin, mà không phải thực hiện một cd, sau đó mv, tại cùng một thư mục?

Ví dụ, tôi phải chạy như sau:

mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt

Lưu ý rằng thư mục nơi tôi di chuyển tệp là như nhau, nhưng tôi phải đặt lại toàn bộ đường dẫn và đôi khi nó gây khó chịu. Tôi tò mò muốn biết liệu có cách nào khác để làm điều đó mà không phải đặt lại toàn bộ đường dẫn không , bởi vì thao tác sẽ được thực hiện theo cùng một đường dẫn.


9
Tôi không thể tin rằng điều này có rất nhiều upvote. Đó là một bản sao unix.stackexchange.com/questions/35782/ , và unix.stackexchange.com/questions/66889/ trộm
user13107

13
@ user13107 Có nhiều cách để đặt câu hỏi, bao gồm cả từ ngữ khác nhau. Và nếu bạn không biết rằng câu trả lời được gọi là "mở rộng cú đúp", bạn có thể không thể tìm thấy nó ngay lập tức.
slhck

2
@ user13107 họ đang ở trên một trang web khác để không trùng lặp
user151019

1
Đánh dấu, Cảm ơn, tôi không biết quy tắc đó về các bản sao. @slhck Vâng. Tôi hiểu. Tôi đã thất vọng vì câu hỏi của tôi về Unix.SE đã bị đóng như là bản sao và câu hỏi này trở nên rất phổ biến.
dùng13107

3
@ user13107, đó là những gì bạn nhận được khi đăng trên đúng trang web
Samuel Edwin Ward

Câu trả lời:


125

Đơn giản chỉ cần sử dụng mở rộng cú đúp :

mv /folder1/folder2/folder3/{file.txt,file-2013.txt}

Điều này tương đương với viết:

mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt

Mở rộng cú đúp cho phép bạn cung cấp nhiều đối số hơn, tất nhiên. Bạn thậm chí có thể vượt qua dãy với nó, ví dụ như để tạo ra một vài thư mục kiểm tra, bạn có thể chạy mkdir test_{a..z}, và bắt đầu với Bash 4, bạn có thể tạo các chuỗi zero-đệm là tốt, như trong touch foo{0001..3}, mà tạo ra foo0001, foo0002foo0003. Các Bash Hacker Wiki có một bài viết với một vài ví dụ cho bạn.

Nếu bạn phải sử dụng hai lệnh khác nhau, cdtrước tiên hãy sử dụng một lệnh con và ở đó, như trong câu trả lời của @ Ignacio .


5
Tôi không biết về việc bracemở rộng, cảm ơn bạn!
Valter Silva

Tôi đã thử và dường như không hoạt động:meniac ~: mv /tmp/f1/f2/f3/f4/f5/f6/{file.txt, file2.txt} mv: cannot stat ``/tmp/f1/f2/f3/f4/f5/f6/{file.txt,': No such file or directory
Valter Silva

5
Bạn có chắc chắn rằng bạn đang sử dụng Bash, như trong /bin/bash, và bạn không ở trong một tập lệnh có /bin/shtrong shebang hoặc một số shell khác không hỗ trợ mở rộng dấu ngoặc? Nếu bạn chạy set, SHELLOPTScó chứa của bạn braceexpand?
slhck

22
Lưu ý rằng không nên có khoảng cách giữa file.txt,file2.txt.
slhck

9
Bạn có thể làm cho nó ngắn hơn nữa, để ngăn lỗi chính tả ở phần không thay đổi:mv /folder1/folder2/folder3/file{,-2013}.txt
Jan Fabry

74

Chạy các hoạt động trong một subshell.

( cd /folder1/folder2/folder3 && mv file.txt file-2013.txt )

Sự thay đổi của thư mục làm việc sẽ không được truyền đến shell cha.


11
+1: Tôi thích cái đó, nhiều khả năng di động trên các vỏ hơn là thủ thuật mở rộng nẹp (gọn gàng, nhưng ít di động hơn)
Olivier Dulac

@Olivier, điều gì khiến bạn nghĩ rằng mở rộng niềng răng không phải là di động? Bạn nghĩ cái vỏ nào không hỗ trợ?
alexis

5
@alexis Mở rộng cú đúp không được chỉ định bởi POSIX nên không thể di động "theo thiết kế". ash, dash, ksh88Chưa kể đến vỏ bourne cũ là ví dụ về vỏ không hỗ trợ nó.
jlliagre

@jlliagre Loại vỏ nào mà bạn đề cập là hoàn toàn phù hợp với POSIX? Điều đó có nghĩa là họ sẽ không mở rộng cú đúp ngay cả khi đó là POSIX. ksh88 là trước khi POSIX được phê chuẩn; bạn nên nâng cấp lên ít nhất ksh93. Hai người duy nhất trong Linux sẽ quan tâm là tro và dấu gạch ngang vì chúng được sử dụng trong một số bản phát hành nhúng nhỏ (busybox, iirc?) Và đĩa cứu hộ.
Kaz

2
@Kaz Tôi quan tâm đến tính di động của các lệnh shell và thực tế chúng có tương tác hay không không quan trọng. Tất nhiên, bạn chắc chắn được tự do không quan tâm đến điều này nhưng xin vui lòng chấp nhận rằng mọi người nghĩ khác. Việc bạn luôn sử dụng bash hoặc shell hỗ trợ mở rộng barce không có nghĩa đó là trường hợp của mọi người.
jlliagre

21

Nếu bạn muốn thông minh, đây là bash mở rộng lịch sử

mv /folder1/folder2/folder3/file.txt !#:1:h/file-2013.txt

Tôi sẽ không sử dụng nó cho bản thân mình vì tôi thấy không thể ghi nhớ. Tôi thỉnh thoảng sử dụng tương đương vim , nhưng phải tìm kiếm nó gần như mọi lúc.


11

Bạn có thể đặt một biến. Tất nhiên điều này có tác dụng phụ của việc để lại các biến xung quanh.

D=/folder1/folder2/folder3; mv $D/file.txt $D/file-2013.txt

Và, tất nhiên, bạn có thể tránh tác dụng phụ của việc để (các) biến xung quanh bằng cách đặt toàn bộ dòng lệnh vào một khung con: (D="/folder1/folder2/folder3"; mv "$D"/file.txt "$D"/file-2013.txt)hoặc đơn giản bằng cách thêm một unsetlệnh ở cuối. (Tôi đã thêm các trích dẫn như một cách thực hành tốt nhất của người Bỉ, nếu bạn có thói quen luôn sử dụng các trích dẫn, bạn sẽ không phải dừng lại và gãi đầu khi một tên đường dẫn chứa các ký tự đặc biệt xuất hiện.)
Scott

@ Hủy bỏ nếu bạn sẽ sử dụng một lớp con để loại bỏ các tác dụng phụ, việc thực hiện cdmột biến sẽ dễ dàng hơn là đặt một biến. Không dễ dàng hơn nhiều , tôi thừa nhận.
Isaac Rabinovitch

2

Tôi thích các giải pháp khác, nhưng đây là một giải pháp khác, được triển khai như một tập lệnh với các mảng bash, Pushd, popd:

#!/bin/bash
set -e
# from http://stackoverflow.com/a/246128/178651
script_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# paths relative to the script
relative_paths=( \
path1 \
path2 \
path3 \
path4
)

for relative_path in "${relative_paths[@]}"
do
  pushd "$script_path/$relative_path" > /dev/null 2>&1
  pwd
  mv filename1 filename2
  # could do other stuff in this directory...
  popd > /dev/null 2>&1
done

pushd "$script_path" > /dev/null 2>&1
# could do other stuff in same directory as script...
popd > /dev/null 2>&1

1

Slhck trực tiếp trả lời câu hỏi theo cách đơn giản nhất có thể, nhưng Valter cũng thích câu trả lời tự động, vì vậy đây là một câu hỏi tương tự;

pushd /folder1/folder2/folder3/; mv file.txt file-2013.txt; popd
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.