lsとmvでms-dosスタイルのワイルドカードを使用する方法は?

lsとmvでms-dosスタイルのワイルドカードを使用する方法は?

私は残念ながらMS-DOSの経験がありますが、少なくともLinuxがどれほど強力であるかを味わいました。私はLinux-Fuを同等のレベルに引き上げようとしましたが、DOSでできることはいくつかありますが、どうすればよいかわかりません。最も簡単Linuxの場合:

複数のファイル名を変更する - 2つのワイルドカードを使用する

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\>rename *.txt *.bak

c:\> dir

Directory of c:\
    file1.bak
    file2.bak
    file3.bak
    file4.bak

ここで使用できることを知っていますが、find -execより短い構文を使用できますか?mv特別なフラグや構文で使用できますか?私の考えでは、ここの鍵は第二 *Linuxのワイルドカードは、最初のワイルドカードでは問題になりません。 (つまり、ワイルドカードを使用して名前を変更するファイルを選択する方法を知っています。)

単一ファイルの名前変更 - ワイルドカードの使用

c:\> dir

Directory of c:\
    file1.txt

c:\>rename file1.txt *.bak

c:\> dir

Directory of c:\
    file1.bak

これは、長く扱いにくいファイル名を変更する場合に特に便利です。私もそれでmv file1.txt $1.bak終わることができると思いましたが、シェルコマンドで引数をインラインで引用できるfile1.txt.bakかどうかはわかりません。$1また、この特別なケースでは、*ms-dosがワイルドカードを使用してファイル名の一部のキャプチャ/置換一致として使用するのが便利です。

ワイルドカードを使用したディレクトリリストのフィルタリング

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt
    text.txt
    \temp       (directory) 

c:\> dir file*

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\> t*

Directory of c:\
    text.txt
    \temp       (directory) 

lsこれを行う正しい構文が何であるか、可能であるかはわかりません。同様の操作をls t*行うとtfind . --max-depth 1 -iname "t*"ls -al | grep tdir t*

最後に、これらの長いコマンドを短縮するためにエイリアスを設定できることを知っていますが、時にはリモートシステムに接続する必要があるため、これらのタスクを実行できる基本的なlinux-fuを学びたいと思います。新しいマシン。

それでは、以前のようにファイルmv操作をどのように使用できますか?lsdirrename

答え1

WindowsシェルとPOSIXシェルの基本的な違いの1つcmdは、ワイルドカード拡張を担当する人が誰であるかです。シェルは、要求された実際のコマンドを実行する前に必要な拡張を実行します。cmd 最大ワイルドカードパターンを変更せずにコマンドに渡します。 (例外があると考え、ほとんどの場合、環境変数が拡張されると思うので、最もよく言います。) これにより、renameと同じ構文で動作するプログラムを作成しますcmd

ただし、Linux用もありますrename。まったく異なるパラメータを使用するマニュアルページを確認してください(私のシステムでは少し簡潔で、広く使用する必要がある私のシステムのパッケージにrenameあります)。util-linux最初の名前の変更は次のように行われます。

rename .txt .bak *.txt

シェルは*拡張を実行するので、rename実際には次のように呼び出されたと思います。

rename .txt .bak file1.txt file2.txt file3.txt ...

したがって、個々のファイルのバージョンを推測できます。

rename .txt .bak file1.txt

使用したくなく、rename自分で実装したい場合は、その関数を作成できます。単一のファイル名の変更に対してファイル拡張子のみを変更する場合は、次の点を確認してください。

$ function chext() {
  newext="$1"
  file="$2"
  newfile="${file%.*}$newext"
  echo mv "$file" "$newfile"
}
$ chext .csv test.txt
mv text.txt text.csv

$newfileを使用して構築されました部分文字列の削除元の拡張を削除し、新しい拡張を添付します。この機能を拡張すると、比較的簡単に複数のファイルを処理できます。


lsあなたの質問には-dスイッチを使用してください。これにより、lsディレクトリの内容が一覧表示されなくなります。

デモ:

$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:29 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.csv
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

ワイルドカードの名前変更

$ rename .csv .txt f*
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

単一ファイル名の変更

$ rename .txt .csv f1.txt 
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

基本ls

$ ls -l t*
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

test:
total 0
-rw-r--r-- 1 owner users 0 Jan  7 17:33 dont_show_me_please

lsディレクトリを確認しないでください

$ ls -ld t*
drwxr-xr-x 2 owner users 4096 Jan  7 17:33 test
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

答え2

ワイルドカードについて話すときに覚えておくべきことの1つは、ワイルドカードがシェルによって拡張されることです。アプリケーションは、ワイルドカードを使用したのか名前を入力したのかわかりません。たとえば、と入力すると、rename *.txt *.bakコマンドrenameに次の内容が表示されますrename file1.txt file2.txt existingfile.bak。この情報では続行できません。

この問題はより簡単なので、最初に取り上げますls。必要なものが名前の一致だけであれば、lsシェルはすでに拡張を行っているので、そうする必要はありません。

echo t*

ファイルに関する追加情報が必要な場合は、オプションを渡してディレクトリの内容を一覧-d表示lsしないように指示してください。

ls -ld t*

ファイル名を変更する標準ユーティリティは、最初のUNIXシステムに付属していなかったためです。ファイルの名前を変更する移植可能な方法はループを使用し、少し冗長です。

for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done

ファイル名を変更するための一般的に使用されるユーティリティはいくつかありますが、特定のUNIXシステムへのインストールは保証されていませんが、すべてインストールが簡単です。主な内容は次のとおりです。

  • renameこのutil-linuxファミリで提供され、すべての非組み込みLinuxシステムで動作します(他のシステムでは機能しません)。 Debianとその派生製品(Ubuntuを含む)では、このコマンドを指しますrename.ul.txt最後の拡張以外に何も表示されない場合は、次のように書くことができます。

    rename .txt .bak *.txt
    
  • renameDebianおよびその派生製品で使用できるPerlスクリプトです/usr/bin/rename。 Perl コマンドに基づいてファイル名を変更できます。

    rename 's/\.txt\z/\.bak/' *.txt
    
  • mmv複数の名前ベースのモードに基づいてファイル名を変更、コピー、リンクすることができ、ターゲット名がすでに存在する場合に発生する状況に関連する多くのオプションがあります。シェルでワイルドカード文字が拡張されないようにするには、引用符を使用する必要があります。

    mmv '*.txt' '#1.txt'
    
  • zmv扱いにくいシェルがzshの場合にのみ使用できる機能です。任意のzshパターンと一致させることができます(したがって、ワイルドカードだけでなく、任意の正規表現に基づいてファイル名を一致させることができ、日付やサイズなどの他の基準に基づいてファイルを一致させることができます)。zmvコピーとリンクも可能です。

    zmv '(*).txt' '$1.txt'
    

使用しているシステムをある程度制御できる場合は、zshをシェルとして使用し(bashと比較して他の利点がある)、次の行を次の行に入れることをお勧めします~/.zshrc

autoload -U zmv
alias zmv='noglob zmv -w'
alias zcp='zmv -C'
alias zln='zmv -L'
alias zsy='zmv -Ls'

noglobコマンド引数でワイルドカード文字を拡張しないようにシェルに指示するzshの機能。これにより、書くことができます(常に代替テキストをzmv *.txt \$1.txt保護する必要があります)。$

関連情報