Bagaimana Anda menggunakan ekspresi reguler dengan perintah cp di Linux?


22

Saya mencoba untuk hanya menyalin subset file dari satu direktori ke direktori lain menggunakan cptetapi saya disambut dengan pesan cp: cannot stat [^\.php]': No such file or directory. Apakah ada cara untuk menggunakan ekspresi reguler hanya dengan menggunakan cpperintah?

Jawaban:


29

Tidak.

The cpperintah tidak memiliki kemampuan untuk memproses argumen sebagai ekspresi reguler. Bahkan wildcard tidak ditangani olehnya (atau sebagian besar executable); melainkan mereka ditangani oleh shell.

cp test/* test2/sebenarnya diperluas oleh bash, dan semua yang cpbenar - benar melihat argumennya adalah cp test/file1 test/file2 test/file3 test2/(atau apa pun yang sesuai berdasarkan isi aktual dari test/).

Juga, saya tidak berpikir ekspresi Anda [^\.php],, akan cocok dengan apa yang Anda inginkan (tidak hanya cocok dengan file yang berisi .php).

Anda mungkin ingin melihat ke findutilitas untuk memfilter daftar file berdasarkan ekspresi reguler, dan kemudian gunakan xargsuntuk menerapkan daftar file yang dikembalikan ke cpperintah (anggap menemukan tidak memiliki penangan bawaan untuk menyalin file; I ' Saya tidak akrab dengan alat ini).

Anda mungkin mencoba:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

Ini mengatakan untuk mencari direktori saat ini secara rekursif untuk file yang tidak mengandung ".php" di path dan salin ke /destination/folder/.

Seperti yang diminta, uraian argumen yang lebih spesifik:

  • . - Lokasi untuk memulai pencarian - dalam hal ini, direktori saat ini
  • ! - "Bukan" operator, balikkan hasil tes berikutnya
  • -iregex- Tes ekspresi reguler case-insensitive. Argumen selanjutnya adalah ungkapan.
  • ".*\.php.*"- Pencocokan ekspresi reguler <Anything>.php<Anything>- File apa pun yang memiliki ".php" di suatu tempat di jalur. (Catatan, termasuk berada di dalam folder yang berisi ".php" dalam nama, Anda akan memerlukan ekspresi yang lebih kompleks untuk hanya mencocokkan file)
  • -exec- Jalankan perintah jika tes sebelumnya mengembalikan nilai true. Argumen selanjutnya adalah perintah, semua argumen tersisa hingga ;diteruskan ke perintah. itu {}adalah argumen khusus yang mewakili nama file.
  • cp - Perintah yang find` harus dijalankan pada masing-masing nama jalur yang cocok.
  • {}- Jalur ke file yang ditemukan, diteruskan cpsebagai argumen sehingga ia tahu file apa yang akan disalin
  • /destination/folder/- Argumen diteruskan ke cp, memberi tahu ke cpmana harus menyalin file.
  • \;- Ini adalah ;terminator yang -execdicari. Kami menghindarinya dengan \shell agar shell Anda tidak mencoba menguraikannya dan sebaliknya memberinya sebagai argumen pada perintah ( find)

Ini agak sulit untuk menulis ekspresi reguler yang cocok "string yang tidak memiliki .php", jadi kita bukannya memberitahu finduntuk mencari string yang tidak mengandung .phpdan kemudian invert hasilnya dengan !.


2
find . -name [^\.php] -exec cp {} /path/to/location \;hati-hati untuk file dengan karakter khusus.
Rob

@Darth Android - Terima kasih. Saya tidak menyadari hal itu cpdan biner lainnya tidak dapat mengembangkan ekspresi reguler. Maukah Anda menguraikan apa yang masing-masing opsi dan argumen maksudkan dalam contoh sampel yang Anda berikan? Saya tahu bahwa .mengacu pada direktori saat ini tapi apa yang !, {}, \;, dll lihat juga apa yang mereka maksud? Misalnya mengapa Anda harus melarikan diri ;?
PeanutsMonkey

@Rob - Apa maksud Anda dengan file khusus?
PeanutsMonkey

@Rob - Saya mencoba ekspresi yang sama untuk menghapus file tertentu namun akhirnya menghapus semua file dalam direktori. find . -name '[^\.txt]' -exec rm {} \;Maka perintah saya adalah keengganan saya untuk menggunakan find. Mungkin kesalahan pada bagian saya tetapi tidak yakin apa yang saya lakukan salah. Sejauh pemahaman saya {}mengacu pada setiap file yang ditemukan oleh perintahfind . -name '[^\.txt]'
PeanutsMonkey

Apa yang ingin dicocokkan dengan regex?
Rob

10

Anda dapat menggunakan beberapa alat lain dari konsol, seperti grep dan xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder

Apa {}bedanya dengan itu -t?
PeanutsMonkey

2
Tidak banyak dalam hal ini. Sintaks alternatif untuk xargs adalah 'xargs cp {} destination_folder'. sintaks cp standar mengambil satu atau banyak sumber dan satu tujuan pada akhirnya, ketika Anda menggunakan opsi -t, Anda dapat menentukan tujuan setelah -t, kemudian menggunakan sisa baris untuk sumber. Saya hanya menemukan opsi -t lebih nyaman dalam hal ini. Dalam contoh lain {} diganti dengan apa yang disalurkan ke xargs (stdin), dalam hal ini nama file.
0xAF

-1

Anda dapat menjalankan perintah berikut yang mudah digunakan:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

haa keren !!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.