ms-dosスタイルのワイルドカードをlsおよびmvで使用するにはどうすればよいですか?


9

私は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などのワイルドカードは最初のものに問題を持つべきではありません

1つのファイルの名前を変更する-1つのワイルドカードを使用する

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*ことをした場合、で始まるディレクトリに再帰しtます。私の回避策は、使用しているか、find . --max-depth 1 -iname "t*"またはそのようなものですls -al | grep t-どちらも、それほど短くて単純でdir t*はありません。

最後に、これらの長いコマンドを短くするためにエイリアスを設定できることはわかっていますが、リモートシステムに接続している場合や作業している場合があるため、これらのことを実行するための標準のlinux-fuについて学びたいと思います新しいマシンで。

だから、どのようにすることができますmvし、ls私が使用するのと同じ方法ファイルdirrenameファイルを?

回答:


15

Windows cmdシェルとPOSIXシェルの基本的な違いの1つは、ワイルドカード拡張の責任者が誰であるかです。シェルは、要求された実際のコマンドを開始する前に、必要なすべての拡張を行います。cmd ほとんどの場合、ワイルドカードパターンを変更せずにコマンドに渡します。(ほとんど例外なく、環境変数はほとんどの状況で展開されると思うので、言います。)これによりrename、と同じ構文で動作するa を作成するのがcmd非常に難しくなります。

しかしrename、Linux にはがあります-引数が完全に異なる場合は、manページをチェックしてください(これは私のシステムでは少し簡潔であり、広く入手できるはずの私のシステムrenameutil-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

非常に素晴らしい!私はlinux-fuでベルトを上げたばかりだと思います!ありがとう!
cwd 2012年

これを少し進めるためのヒント(および落とし穴を避けるため):単純な関数またはスクリプトを使用してsomefunc *.Ext、そのパターンがどのファイルとも一致しない場合に何が起こるかを確認し、引用符で遊んで、パターンをうまく渡せたかどうかを確認します(関数間で展開する必要はありません。安全のためのヒント:グロビング/シェル展開の実験中はどこも使用しないでくださいrm :-)
Mat

4

ワイルドカードに関しては、シェルによって展開されることを覚えておいてください。アプリケーションは、ワイルドカードを使用したか、名前を入力したかを知りません。たとえば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システムにインストールされることが保証されていませんが、すべて簡単にインストールできます。主なものは次のとおりです。

  • renameutil-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の場合のみです。任意の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$置換テキストで常に保護する必要があります)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.