Ganti nama banyak file dengan mv untuk mengubah ekstensi

27

Saya ingin mengubah nama file untuk mengubah ekstensi mereka, secara efektif ingin dicapai

mv *.txt *.tsv

Tetapi ketika melakukan ini saya mendapatkan:

* .tsv bukan direktori

Saya merasa agak aneh bahwa 10 hits google show pertama mvharus bekerja seperti ini.

Sander Van der Zeeuw
sumber
Anda harus menjelaskan bagaimana Anda ingin mengganti nama file-file itu dengan tepat.
Totor
1
Yah saya punya file dengan ekstensi * .gappedPeak dan ingin mengubah nama mereka menjadi * .bed. mereka semua berada di direktori yang sama, itu harus sangat sederhana tetapi diperlukan loop penuh agar saya berhasil
Sander Van der Zeeuw
Apa yang Anda temukan di Google berlaku untuk MSDOS saya pikir.
tiktak
Solusi alternatif @devnull sangat membantu
lucasvw

Jawaban:

22

Saat Anda mengeluarkan perintah:

mv *.txt *.tsv

shell, mari kita asumsikan bash, perluas wildcard jika ada file yang cocok (termasuk direktori). Daftar file diteruskan ke program, di sini mv. Jika tidak ada kecocokan yang ditemukan, versi yang tidak dikembangkan dilewatkan.

Sekali lagi: shell memperluas polanya, bukan programnya.


Banyak contoh mungkin cara terbaik, jadi di sini kita mulai:

Contoh 1:

$ ls
file1.txt file2.txt

$ mv *.txt *.tsv

Sekarang yang terjadi di mvtelepon adalah bahwa shell mengembang *.txtke file yang cocok. Karena tidak ada *.tsvfile yang tidak diubah.

The mvperintah disebut dengan dua argumen istimewa :

  • argc: Jumlah argumen, termasuk program.
  • argv: Array argumen, termasuk program sebagai entri pertama.

Dalam contoh di atas itu akan menjadi:

 argc = 4
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = file2.txt
 argv[3] = *.tsv

The mvprogram pemeriksaan untuk melihat apakah argumen terakhir, *.tsv, adalah sebuah direktori. Karena tidak, program tidak dapat melanjutkan karena tidak dirancang untuk menggabungkan file. (Biasanya memindahkan semua file menjadi satu.) Atau membuat direktori dengan hati-hati.

Akibatnya, ini membatalkan dan melaporkan kesalahan:

mv: target ‘*.tsv’ is not a directory

Contoh 2:

Sekarang jika Anda mengatakan:

$ mv *1.txt *.tsv

The mvperintah dijalankan dengan:

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = *.tsv

Sekarang, sekali lagi, mvperiksa untuk melihat apakah *.tsvada. Karena tidak file file1.txtdipindahkan ke *.tsv. Yaitu: file diubah namanya menjadi *.tsvasterisk dan semuanya.

$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’

$ ls
file2.txt *.tsv

Contoh 3:

Jika Anda sebaliknya berkata:

$ mkdir *.tsv
$ mv *.txt *.tsv

The mvperintah dijalankan dengan:

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[1] = file2.txt
 argv[2] = *.tsv

Karena *.tsvsekarang adalah direktori, file akhirnya dipindahkan ke sana.


Sekarang: menggunakan perintah seperti some_command *.tsvketika tujuannya adalah untuk benar-benar mempertahankan wildcard, orang harus selalu mengutipnya. Dengan mengutip Anda mencegah wildcard tidak diperluas jika harus ada kecocokan. Misalkan katakan mkdir "*.tsv".

Contoh 4:

Perluasan lebih lanjut dapat dilihat jika Anda lakukan misalnya:

$ ls
file1.txt file2.txt

$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists

Contoh 5:

Sekarang: mvperintah dapat dan berfungsi pada banyak file. Tetapi jika ada lebih dari dua yang terakhir harus menjadi direktori target. (Secara opsional Anda dapat menggunakan -t TARGET_DIRopsi, setidaknya untuk GNU mv.)

Jadi ini tidak masalah:

$ ls -F
b1.tsv  b2.tsv  f1.txt  f2.txt  f3.txt  foo/

$ mv *.txt *.tsv foo

Di sini mvakan dipanggil dengan:

 argc = 7
 argv[0] = mv
 argv[1] = b1.tsv
 argv[2] = b2.tsv
 argv[3] = f1.txt
 argv[4] = f2.txt
 argv[5] = f3.txt
 argv[6] = foo

dan semua file berakhir di direktori foo.


Adapun tautan Anda. Anda telah memberikan satu (dalam komentar), di mana mvtidak disebutkan sama sekali, tetapi rename. Jika Anda memiliki lebih banyak tautan, Anda dapat membagikannya. Juga untuk halaman manual di mana Anda mengklaim ini diungkapkan.

Runium
sumber
30

Saya tahu ini tidak menjawab pertanyaan Anda, tetapi jika Anda mencari cara lain untuk mengganti nama file dibandingkan dengan loop penyelesaian Anda, mengapa tidak digunakan find? Saya telah menggunakan perintah ini berkali-kali untuk mengganti ekstensi file di direktori besar dengan ratusan ribu file di dalamnya. Ini harus bekerja pada sistem yang mendukung POSIX:

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;

Perintah Breakdown:

  1. ' .' => jalur pencarian mulai dari direktori saat ini ditandai dengan '. '

  2. -name=> atur find match name (dalam hal ini semua file yang diakhiri dengan .gappedPeak)

  3. -exec => jalankan perintah berikut pada setiap pertandingan

  4. sh -c => 'exec' menciptakan lingkungan shell independen untuk setiap pertandingan

  5. mv "$1" "${1%.gappedPeak}.bed"=> mvvariabel pertama (dilambangkan dengan $ 1 ), yang merupakan nama file saat ini, ke nama baru. Di sini saya melakukan pencocokan substring dan menghapus; jadi ambil var pertama lagi, $ 1 dan gunakan %untuk menghapus .gappedPeakdari string. Pada .bedakhirnya hanya menggabungkan variabel yang tersisa, yang sekarang hanya , dengan , menciptakan nama file baru .test#.bedtest#.bed

  6. Garis bawah adalah pengganti untuk $ 0

  7. The {}digantikan oleh masing-masing ( *.gappedPeak) nama file yang ditemukan oleh findperintah, dan menjadi $ 1 ke shperintah.

  8. \;menandai akhir dari -execperintah. Anda juga dapat menggunakan ';'atau ";".

Contoh:

[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak

[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed
devnull
sumber
Bisakah Anda melewati perintah yang menggambarkan apa yang dilakukan masing-masing bagian?
user1717828
Saya minta maaf tentang itu, saya memperbarui posting saya. Semoga itu bisa membantu.
devnull
1
Keren terima kasih! Dengan panduan bash dan penjelasan Anda, saya bisa mendapatkan semuanya.
user1717828
Tidak masalah. Senang itu bisa membantu.
devnull
Bekerja seperti pesona. Berikut contoh sederhana lain untuk file.abc-> blub.xyzdalam beberapa subdirektori:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
Mahn
9

mv *.txt *.tsvtidak bekerja; mvhanya dapat mengganti nama satu file pada satu waktu. Anda salah memahami penjelasannya atau salah.

mmvdan renamedapat mengganti nama beberapa file sekaligus. Tetapi ada dua versi renamesekitar yang disebut berbeda. Seharusnya ada banyak pertanyaan tentang itu di sini.

Hauke ​​Laging
sumber
1
cyberciti.biz/tips/... Hit pertama di google mengatakan bahwa mv harus bekerja juga karena itulah saya merasa sangat aneh
Sander Van der Zeeuw
3
@SanderVanderZeeuw Saya tidak tahu apa yang Anda baca di sana. Contohnya menggunakan rename, bukan mv.
Hauke ​​Laging
1
maaf saya menyisipkan HTML yang salah. Ini adalah udemy.com/blog/rename-a-file-in-linux
Sander Van der Zeeuw
3
@SanderVanderZeeuw Memalukan. Orang-orang ini menawarkan kursus? Sayangnya saya tidak melihat kemungkinan kontak di sana. Anda dapat dengan mudah memeriksa apakah ini berfungsi. Namun dalam mv *.txt *.tsv mv(biasanya) tidak melihat *.txtatau *.tsvtetapi nama file diperluas shell. Jumlah file yang diperluas ke wildcard ini akan menjadi "acak". Satu-satunya situasi di mana ini bekerja adalah jika ada file dengan nama *.txtyang akan diubah namanya menjadi (secara harfiah) *.tsv(tanpa mengutip bashopsi nullglobtidak boleh diatur).
Hauke ​​Laging
1
Atau lebih buruk. Jika salah satu memiliki satu file bernama misalnya foo.txtdan satu bernama baz.tsvyang mv *.txt *.tsvakan menimpa yang ada .tsvfile ...
Runium
4

Sebagai contoh, jika Anda memiliki asd.txtdan qwe.txtfile dalam direktori ketika Anda menjalankan perintah mv *.txt *.tsv, ia mencoba untuk memindahkan dua file ini ke dalam direktori bernama *.tsv. Karena tidak ada direktori seperti itu, itu memberikan kesalahan.

Esref
sumber
Terima kasih, ini menjelaskan sebagian. Masih saya merasa aneh bahwa saya melihat begitu banyak halaman manual di mana mereka mengklaim saya harus bekerja pada banyak.
Sander Van der Zeeuw
2

rename(1)

renameadalah skrip perl oleh Larry Wall pembuat perl. Dibutuhkan regex Perl dan beroperasi pada nama file.

rename 's/\.txt$/.tsv/' *.txt

Instalasi

Debian / Ubuntu

Jika Anda perlu menginstal renamedi Debian / Ubuntu yang dapat Anda lakukan

sudo apt install rename
Evan Carroll
sumber
0

Pilihan lain untuk dipertimbangkan adalah menggunakan:

cp -p *.txt *.tsv
rm -f *.txt
  • Baris pertama menyalin semua *.txtfile *.tsvsambil mempertahankan atribut mereka menggunakan -pflag.
  • Baris kedua menghapus semua file dengan pola *.txt
  • Metode ini mengharuskan Anda memiliki ruang disk yang cukup untuk menyimpan sementara file sumber dan target
  • Metode ini lebih lambat daripada mvyang hanya mengubah / direktori / nama file tanpa benar-benar memindahkan file kecuali mereka berada di partisi yang berbeda.
WinEunuuchs2Unix
sumber