File mv Linux dengan nama panjang

19

Di Linux saya terkadang mengganti nama file seperti ini:

mv dir1/dir2/dir3/file.txt  dir1/dir2/dir3/file.txt.old

Perhatikan bahwa saya hanya ingin mengganti nama file, tidak memindahkannya ke direktori lain.

Apakah ada perintah yang memungkinkan saya melakukan versi singkat dari perintah itu? Saya sedang memikirkan sesuatu seperti:

mv dir1/dir2/dir3/file.txt  file.txt.old

atau mungkin bahkan sesuatu seperti (hanya menambahkan nama):

mv dir1/dir2/dir3/file.txt  {}.old

Tujuan saya adalah tidak harus menentukan path lengkap lagi.

Saya tahu "contoh-contoh" yang saya tulis itu tidak berhasil, tetapi itu hanyalah gagasan tentang apa yang ingin saya capai.

Saya tidak mau harus masuk ke direktori.

santiago arizti
sumber
8
Mengapa Anda tidak mengubah ke direktori? Cepat dan menyelesaikan masalah Anda.
Michael Hampton
Saya berurusan dengan banyak subdirektori dari lokasi yang sama ini, lebih lambat jika saya harus kembali ke dir induk ini setiap kali
santiago arizti
3
Tidak ada yang mengatakan Anda harus mengubah ke direktori lain, hanya yang Anda inginkan.
Michael Hampton
Catatan yang (cd dir1/dir2/dir3 && exec mv file.txt{,.old})secara efektif memiliki kinerja yang sama dengan kode tanpa subproses, karena execmenghindari fork()selama permintaan perintah eksternal, sehingga Anda memiliki tepat satu garpu jalan baik.
Charles Duffy

Jawaban:

45

untuk satu file coba

mv dir1/dir2/dir3/file.{txt,txt.old}

tempat X{a,b}konstruksi berkembang Xa Xb, Anda dapat menggunakan pratinjau menggunakan

echo dir1/dir2/dir3/file.{txt,txt.old}

untuk melihat apakah itu sesuai dengan kebutuhan Anda.

catatan:

  1. itu untuk banyak file

    mv dir1/dir2/dir3/file{1,2,3}.{txt,txt.old}
    

tidak mungkin berkembang ke apa yang Anda inginkan. (ini akan diperluas ke campuran file.txt file1.txt.old file2.txt ...)

  1. {txt,txt.old}dapat disingkat menjadi {,.old}sesuai komentar

  2. jika nama direktori tidak ambigu, wildcard dapat digunakan.

    mv *1/*2/d*/*.{,old}
    

untuk penggunaan banyak file rename

rename -n s/txt/old.txt/ dir1/dir2/dir3/file*.txt 

drop -nuntuk memiliki nama yang efektif.

Archemar
sumber
1
bagus, saya tidak tahu cara memperluas ini! terima kasih
santiago arizti
14
Tidak mv dir1/dir2/dir3/file.txt{,.old}juga bekerja, dan bahkan lebih pendek?
Josh
3
@ Ya. Ya, itu bekerja dengan sempurna dan lebih sedikit penekanan tombol. Saya menggunakan konstruksi ini secara teratur.
Jika
2
itu lucu bagaimana Anda dapat menggunakan shell Linux selama bertahun-tahun dan masih menemukan trik baru setiap saat
santiago arizti
Saya kira semua "trik" itu akan lebih jelas jika saya memiliki beberapa pelatihan formal dalam bahasa bash, tetapi saya baru saja belajar cukup untuk bergaul.
santiago arizti
6

Perintah renamemengganti nama semua file yang cocok. Tujuan utamanya adalah untuk mengubah nama banyak file, tetapi jika ekspresi Perl hanya cocok dengan satu file, maka itu akan mengubah nama hanya file tunggal ini. Untuk rincian dan sintaks khusus distro silahkan baca manual ini: man rename.

Contoh penggunaan: ganti nama "/path/file.txt" menjadi "/path/file.txt.old":

rename 's/file.txt/file.txt.old/g' /path/file.txt

Notasi lebih pendek (terima kasih kepada shalomb):

rename 's/$/.old/' /path/file.txt
rename '$_.=".old"' /path/file.txt

Untuk penggunaan jangka kering rename -n.

Lebih banyak contoh dan detail dapat ditemukan di https://thepcspy.com/read/bulk-rename-files-in-ubuntu/

Fabian
sumber
keren, saya tahu tentang perintah ganti nama, hanya tidak pernah tahu semua itu bisa dilakukan, terima kasih!
santiago arizti
6
Sayangnya distribusi Linux yang berbeda memiliki renameperintah yang berbeda dengan perilaku yang sama sekali berbeda.
kasperd
1
Untuk tugas penggantian nama dengan menambahkan .oldnama file ini, mungkin sedikit lebih mudah untuk melakukan rename 's/$/.old/' /path/to/file.txtataurename '$_.=".old"' /path/to/file.txt
shalomb
@Fabian - Saya tidak melakukan nitpicking, hanya bertujuan untuk "tangan terpendek" untuk apa yang tampaknya menjadi idiom yang sering digunakan OP sedang mencari :)
shalomb
4

Untuk kasus satu kali, jika saya tidak ingin mengubah direktori saya saat ini, saya mungkin menggunakan sub-shell:

(cd dir1/dir2/dir3/ && mv file.txt file.txt.old)

Karena Anda cdberada di dalam sub-shell, Anda belum mengubah direktori di shell Anda yang sebenarnya

Adam
sumber
4
Lebih cepat dan lebih aman untuk digunakan && exec mv- dengan cara itu Anda tidak mencoba untuk melakukan penggantian nama jika cdgagal, dan execmengkonsumsi subkulit, sehingga menghindari penalti kinerja.
Charles Duffy
Setuju dengan && Untuk satu kasus, seperti yang saya katakan, saya tidak akan khawatir tentang biaya sub-shell (tetap sederhana: bisa dengan mudah mengingat bagaimana melakukannya adalah IMO yang lebih penting)
Adam
Aku berpendapat bahwa jika Anda akan ingat hanya satu cara, mengingat cara yang efisien membantu memastikan Anda tidak pergi rute yang tidak efisien dalam kasus di mana itu tidak peduli.
Charles Duffy
4

Saya suka solusi @ archemar menggunakan ekspansi {}, karena Anda dapat menggunakannya ketika Anda sudah memulai baris perintah Anda. Berikut beberapa kemungkinan lain untuk kelengkapan:

F="dir1/dir2/dir3/file.txt" ; mv "$F" "$F.old"

(Kutipan hanya diperlukan jika Anda memiliki spasi atau karakter pemecah kata lainnya dalam nama)

mymv() {
    mv "$1/$2" "$1/$3"
}

mymv dir1/dir2/dir3 file.txt file.txt.old
mymv dir5/dir6/dir7 file.txt file.txt.old

Catatan:

  • Ini adalah sintaks bash, Anda mungkin menggunakan shell lain
  • mymv bisa berupa string yang masuk akal, saya menggunakan mymv untuk "my move".
  • Definisi fungsi dapat dimasukkan ke dalam .bash_profile Anda

Yang lainnya:

cd dir1/dir2/dir3 ; mv file.txt file.txt.old ; cd -

tapi

(cd dir1/dir2/dir3/ && exec mv file.txt file.txt.old)

(dari @Adam dan @CharlesDuffy) bisa dibilang lebih baik jika cd gagal.

Hukum29
sumber
1
Jangan gunakan mmv, sudah ada program bernama cara ini.
glglgl
1
@glglgl Selesai :)
Law29
2

Jika Anda ingin memasukkan subdirektori untuk mempersingkat mvperintah, tetapi ingin kembali ke direktori saat ini setelahnya, ada dua cara untuk melakukannya. Salah satunya adalah dengan meletakkan cddan mvdalam subkulit (seperti yang telah disarankan).

Yang lainnya adalah menggunakan pushddan popdmengubah direktori:

pushd dir1/dir2/dir3/; mv file.txt file.txt.old; popd

The pushdperintah seperti cd, kecuali pertama kali mendorong nama direktori saat ini ke tumpukan. popdmenghapus nama teratas dari tumpukan dan mengubah ke direktori itu.

AndyB
sumber
pushddan popdekstensi dimaksudkan untuk penggunaan interaktif - POSIX secara eksplisit mencantumkannya sebagai "hasil tidak ditentukan", dan shell yang dibuat untuk menjalankan skrip (mis. pada lingkungan seminimal mungkin tertanam) tidak perlu mendukungnya.
Charles Duffy
2

Saya hanya akan melakukannya

cd dir1/dir2/dir3/
mv file.txt file.txt.old
cd ~- # go to the most recent directory
glglgl
sumber
0

Solusi yang melibatkan: mv something{.txt,.txt.old}menggunakan "bashism". Jika Anda menginginkan cara yang lebih portabel, gunakan manipulasi variabel umum:

# rename all files "file*.txt" of directory /dir1/dir2/dir3 into file*.txt.old:
for f in dir1/dir2/dir3/file*.txt ; do
  mv "$f" "${f/.txt/.txt.old}"  # note there are no terminating "/"
done


# "${var/A/B}" is the content of var with the first occurence of "A" replaced by "B"
Olivier Dulac
sumber
2
Lihat pubs.opengroup.org/onlinepubs/009695399/utilities/... untuk spesifikasi POSIX terkait - ${var/text/replacement}adalah bashism itu sendiri.
Charles Duffy
@CharlesDuffy oh ... Anda membuat saya sedih :(
Olivier Dulac