Apakah ada cara untuk mendapatkan shell windows cmd untuk memperluas jalur wildcard?

37

Kadang-kadang, ketidakmampuan shell CMD untuk memperluas jalur wildcard benar-benar bisa menjadi ketidaknyamanan. Saya harus melewatkan 100 file dalam direktori ke program, dan tidak bisa mengetik * .ext. Sebagai gantinya, saya menggunakan 'ls' mingw untuk membuang daftar ke file, kemudian mengganti baris baru dengan spasi, disalin dan disisipkan ke cmd. Cukup mimpi buruk.

Saya curiga jawabannya adalah tidak, tetapi adakah yang sudah menangani ini atau mencari cara untuk membuatnya lebih mudah?

mencemari
sumber
2
Sudahkah Anda mempertimbangkan untuk menggunakan sesuatu seperti Powershell?
I suspect the answer will be no, but has anyone dealt with this or come up with any way to make this easier? Sebenarnya, saya memiliki masalah yang berlawanan, saya mencoba mencari cara untuk membuat penerjemah perintah memperlakukan daftar sebagai string dan mencegahnya tidak menginstruksikan mereka sebagai wildcard. Sebagai contoh, for %i in (foobar baz really?) do @echo %iakan memperlakukan item terakhir ( really?) sebagai wildcard nama file, dan lewatkan saja jika tidak ada file bernama really1, reallyz, dll ☹
Synetech
1
@Synetech - ?bukan karakter hukum untuk nama file di sistem file Windows. Karakter hanya dapat diartikan sebagai wildcard. Lihat Menamai File, Paths, dan Namespaces di MSDN dan Menggunakan karakter wildcard di TechNet.
jww

Jawaban:

18

DOS, dan akibatnya Windows cmd.exe, tidak pernah mendukung ekspansi wildcard oleh shell. Selalu tergantung pada aplikasi untuk melakukan ekspansi.

Ini berarti Anda akan selalu harus menemukan rute lain jika Anda menggunakan aplikasi yang tidak mendukung ekspansi. Anda bisa:

  • Gunakan loop FOR untuk menjalankan beberapa perintah terhadap semua file yang Anda minati
  • Gunakan dir /b > list.txtuntuk menggunakan dirperintah untuk melakukan ekspansi dan meletakkan daftar file ke file teks (Anda kemudian bisa menggunakan sesuatu seperti rumus Excel jika Anda benar-benar putus asa untuk menghasilkan daftar perintah untuk ditempelkan ke dalam cmd, atau Anda bisa menggunakan Excel untuk mengubah urutan sel sehingga semua nama file berada pada baris yang sama.)
Malvine
sumber
Dia menjelaskan bahwa itu akan menjadi mimpi buruk untuk menampilkan hasil dir ke file dan proses penyaringan dan penyalinan secara manual. jawaban wmz dan tentu saja milikku akan bekerja tanpa secara manual memfilter konten file.
wullxz
1
@wullxz: Mungkin, tetapi bagi seseorang yang tidak terbiasa dengan Powershell yang ingin melakukan ini satu kali, itu bisa menjadi jauh lebih cepat - dan ide di balik situs ini adalah untuk memberikan solusi yang berguna bagi orang-orang dari semua tingkat keterampilan untuk merujuk sekarang dan di masa depan, jadi benar-benar tidak perlu memberitahuku karena kau pikir jawabanku tidak sebaik jawabanmu.
Malvineous
1
"DOS, dan akibatnya cmd.exe Windows, tidak pernah mendukung ekspansi wildcard oleh shell." - Tidak benar menurut Microsoft. Lihat Menggunakan karakter wildcard di TechNet. (Tapi saya pikir Anda benar dalam praktik: o. Jika tidak, saya tidak akan berada di sini mencoba mencari tahu mengapa file tidak cocok)
jww
1
@jww: Tautan yang Anda poskan menjelaskan penggunaan standar karakter wildcard, tapi saya tidak bisa melihat penyebutan yang diperluas oleh shell. Tidak seperti UNIX (dan kemudian Linux dan Mac), Microsoft membiarkan ekspansi wildcard hingga masing-masing aplikasi untuk diimplementasikan, melewati parameter baris perintah melalui apa adanya.
Malvineous
1
Perintah DOS 'dir Filespec / b' bekerja dengan sangat baik, karena ia membuat daftar file, satu per baris. Dengan sakelar '/ s' tambahan, nama file sepenuhnya memenuhi syarat (absolut), dan dapat dengan mudah dimasukkan melalui loop for ke program baris perintah lainnya yang menggunakan nama file. Itu yang terbaik yang bisa kita lakukan, karena Windows tidak memiliki fitur globbing yang tepat.
David A. Gray
9

Cukup gunakan Powershell, yang sudah diinstal pada Windows 7. Powershell mampu menjalankan perintah cmd dan mengerti wildcard di setiap tempat di jalan.

Untuk memulai Powershell cukup ketik "PowerShell" di kotak pencarian menu mulai dan tekan enter.


Jika aplikasi mengharapkan string dengan semua nama file di dalamnya, ini adalah skrip yang tepat:

$delimiter = " "
[string]$files = $nothing ; ls *.txt | % { $files += $_.fullname + $delimiter } ; application.exe $files

Ubah $delimiter = " "ke $delimiter = ","jika aplikasi Anda mengharapkan daftar nama file yang dipisahkan koma.

Penjelasan kode:

  • [string]$files = $nothing - Membuat variabel tipe kosong string
  • ; - adalah pemisah untuk banyak perintah, bukan saluran pipa!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - Mendapat daftar semua file teks dan membuat string dengan semua nama file yang dipisahkan oleh pembatas
  • application.exe $files - memanggil aplikasi dan meneruskan daftar file ke sana

Anda bahkan dapat mencari pola berkas secara rekursif dengan menambahkan -recurseke ls *.txtsehingga kode lengkap akan terlihat seperti ini:

$delimiter = " "
[string]$files = $nothing ; ls *.txt -recurse | % { $files += $_.fullname + $delimiter } ; application.exe $files

Sunting:
Untuk menghindari iritasi, lsdan diralias Get-ChildItematau %merupakan alias untuk ForEach-Object. Saya menyimpan kode saya dengan alias yang digunakan karena lebih pendek.

EDIT 2018/04/25:
Kembali pada tahun 2012, saya sudah cukup baru di PowerShell. Tentu saja ada cara yang lebih mudah meskipun tidak semudah kemampuan ekspansi glob unix / linux:

app.exe $(ls *.txt | % {$_.FullName})

Penjelasan:

  • $ () akan mengevaluasi ekspresi di dalam terlebih dahulu dan akan mengganti dirinya dengan output dari ekspresi itu (seperti backticks di bash)
  • ls *.txt mendapat objek FileInfo dari semua file yang cocok dengan glob *.txt
  • karena PowerShell berorientasi objek, kita harus menampilkan nama lengkap setiap objek FileInfo. Cukup memberi nama atribut / properti di PowerShell outputs secara default. % { $_.FileName }melakukan itu untuk kita. %loop atas semua elemen yang dikembalikan oleh lsdan menampilkan setiap objek FileName.
wullxz
sumber
2
Meskipun PS tentu saja mampu memenuhi persyaratan dan saran untuk membiasakannya dengan suara - tidak sesederhana yang Anda sarankan. Menjalankan start notepad++ *.txt(dengan maksud untuk membuka semua textfiles - notepad digunakan ++ seperti halnya menangani beberapa nama) akan mendapatkan tempat
WMZ
1
Anda bisa mengatasinya dengan dir *.txt | % { notepad++.exe $_ }. Saya mencobanya dengan notepad sederhana, karena saya tidak punya notepad ++, dan itu berhasil. Perintah menerima daftar semua file txt di direktori saat ini, meneruskan daftar ke perintah berikutnya yang melewati daftar dan mengeksekusi notepad ++ dengan nama file sebagai parameter.
wullxz
ya, tapi ini tidak setara. Pikirkan grep "a b c"untuk menemukan salah satu string yang terdaftar, di mana "ab c" akan diperluas daftar
wmz
5
Menjalankan perintah dengan daftar item sebagai parameter tidak setara dengan menjalankan perintah beberapa kali dengan setiap elemen dari daftar sebagai parameter. Contoh lain: copy a+b+c resultdan copy a result copy b result copy c result. (dan grep seperti utilitas memang ada di PS, itu disebut select-string)
wmz
1
terbalik, tapi sayang OP tidak peduli untuk menjelaskan ...
wmz
8

Ini akan memberi Anda daftar dan juga memasukkannya ke dalam variabel bernama expanded_list. Masukkan ke dalam file batch dan jalankan myBatchFile name myPattern. Lampirkan pola dengan tanda kutip jika termasuk spasi. Cocokkan file, tanpa dir. Jalankan tanpa parameter cocok dengan semua.

@echo off
set expanded_list=
for /f "tokens=*" %%F in ('dir /b /a:-d "%~1"') do call set expanded_list=%%expanded_list%% "%%F"

echo expanded_list is: 
echo %expanded_list%

Anda kemudian dapat menjalankan perintah Anda dengan my_command_exec %expanded_list%

PERINGATAN! Ukuran maksimum variabel cmd adalah 8191 karakter (XP dan seterusnya), jadi mungkin saja untuk melimpah! Anda tidak dapat mengandalkan utilitas untuk selalu memberi Anda daftar lengkap. Di sisi lain, panjang garis cmd maksimum juga 8191 sehingga Anda tidak akan bisa menjalankannya.

wmz
sumber
Catatan jika tidak ada argumen yang ditentukan maka diperluas_list akan diatur ke semua file dalam direktori saat ini yang mungkin atau mungkin tidak diinginkan sehingga mungkin ingin menambahkan cek tanpa argumen (misalnya jika "% 1" == "" ...)
JasonM1
3

Ini berfungsi di cmd.exe

dir /b *.ext

atau

echo | dir /b *.ext
pengguna619818
sumber
Ini hanya berfungsi untuk nama file, bukan bagian mana pun dari path. Misalnya dir /b TortoiseSVN\bin\sv*.exeakan ditampilkan svn.exedan svnadmin.exe. Tetapi dir /b TortoiseSVN\bi*\svn.exemenunjukkan kesalahan sintaksis.
styfle
1
periksa dir /s /b. Ini memberi Anda jalan penuh.
WesternGun
3

Catatan, ini ada di Komentar untuk poster di utas terpisah user619818 dan tembus)

DIR dapat dan memang memungkinkan mencari semua subdirektori untuk file yang cocok dengan jenis tertentu.

Catatan: Direktori Root untuk memeriksa di mana semua subdirektori berada di bawah diasumsikan "C: \ My Program \ Root \" karena penulis tidak memberikan nama jalur di mana direktori ini berada

DIR /B /S "C:\My Program\Root\*.ext"

ini akan memberikan path file lengkap dan nama file dari file sumber.

jika Anda hanya ingin nama file, Anda harus melakukan sebagai berikut

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( Echo.%~nxA )

jadi dengan asumsi Anda ingin memindahkan semua file ini dari "C: \ My Program \ Root \ Sub Directories \ *. ext" ke "D: \ Singlefolder \ *. ext" Anda cukup melakukan ini:

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( MOVE "%~A" "D:\Singlefolder\%~nxA" /Y )

Harapan yang membantu orang lain di masa depan. :)

Ben Personick
sumber
1

Ini sudah tua, tetapi dengan subsistem Linux untuk windows, cukup umum untuk memiliki bash di PATH Anda sekarang. Jika itu masalahnya, maka ini mungkin melakukan trik untuk Anda:

bash -c 'cat *.txt'
Richard
sumber
perhatikan bahwa tanda kutip tunggal tidak spesial di Windows cmd , jadi jika Anda menjalankan perintah di atas dari cmd itu tidak akan berfungsi. Dan ini juga berlaku untuk sistem dengan Cygwin atau lingkungan bash lainnya
phuclv