web-dev-qa-db-ja.com

'ls -1':拡張子なしでファイル名をリストする方法

ls -1は次のように私の要素をリストします:

foo.png
bar.png
foobar.png
...

次のように.pngなしでリストしたい:

foo
bar
foobar
...

(dirには.pngファイルのみが含まれます)

この場合のgrepの使い方を誰かに教えてもらえますか?

目的:すべての名前が拡張子なしでリストされているテキストファイルがあります。テキストファイルとフォルダーを比較して、不足しているファイルを確認するスクリプトを作成したいと考えています。

27
Colin

このジョブに必要なのはシェルだけです。

POSIXly:

for f in *.png; do
    printf '%s\n' "${f%.png}"
done

zshの場合:

print -rl -- *.png(:r)
45
cuonglm
ls -1 | sed -e 's/\.png$//'

sedコマンドは、ファイル名のendで見つかった文字列.pngを削除します(つまり、空の文字列で置き換えます)。

.\.としてエスケープされるため、正規表現.ではなく、sedがリテラル.文字として解釈されます(つまり、任意の文字に一致します) )。 $は行末アンカーなので、ファイル名の途中の.pngとは一致しません。

38
cas

Bashを使用したいだけの場合:

for i in *; do echo "${i%.png}"; done

一致を見つけようとするときはgrepに手を伸ばす必要があります。その代わりにsedを使用するのは適切ではありません。

find . -maxdepth 1 -name "*.png"  | sed 's/\.png$//'

PNGファイルに順序を付けるためにいくつかのサブディレクトリを作成する必要があると判断したら、簡単に次のように変更できます。

find . -name "*.png"  | sed 's/\.png$//'
16
Anthon

私はbasenameに行きます(GNU実装を想定):

basename --suffix=.png -- *.png
13
hennr

別の非常によく似た答え(この特定のバリアントがまだ表示されていないことに驚いています)は次のとおりです。

ls | sed -n 's/\.png$//p'
  • lsは、標準出力がターミナルではない場合(この場合はパイプ)を想定しているため、lsに対する-1オプションは必要ありません。
  • sed-nオプションは、「デフォルトでは行を印刷しない」ことを意味します
  • 置換の最後にある/pオプションは、「...置換が行われた場合にこの行を出力する」ことを意味します。

その最終的な効果は、.pngを削除して、.pngで終わる行だけを出力することです。つまり、これはOPの質問のわずかな一般化にも対応しています。つまり、ディレクトリには.pngファイルのみが含まれていません。

sed -n手法は、通常はgrep + sedを使用する可能性がある場合に役立ちます。

12
Norman Gray

これを行うには、BASHコマンドのみを使用できます(外部ツールなしで)。

for file in *; do echo "${file%.*}"; done 

これは、/ usr/binがない場合に便利で、this.is.image.pngのようなファイル名とすべての拡張子に対して機能します。

lsを解析したり、findをパイプしたりするのは安全ではありません[ 12 ]

lsまたはfindの出力を解析(およびパイプ)するのは安全ではありません。主にファイル名で見つけることができるためです改行タブなどの通常ではない文字...ここでは、純粋なシェルサイクルが機能します[ cuonglm ]
findコマンドパイプなしオプション-execでも機能します。

find ./*.png  -exec  basename {} .png  \;

pdates/Notesfind .を使用して非表示のファイルを検索することも、find ./*.pngを使用して非表示でないファイルのみを取得することもできます。 find *.png -exec ...を使用すると、.pngという名前のファイルが存在する場合に問題が発生する可能性があります。これは、findがオプションとして取得するためです。 -maxdepth 0を追加すると、Dir_01.pngという名前のディレクトリへの下降を回避できます。また、maxdepthが許可されていない場合はfind ./*.png -Prune -exec ...を追加できます(Stéphaneに感謝)。これらのディレクトリのリストを表示したくない場合は、オプション-type fを追加する必要があります(これにより、他のタイプの非通常ファイルも除外されます)。 manを調べて、利用可能なすべてのオプションの完全なパノラマを確認し、移植性を高めるために、それらがPOSIX準拠であるかどうかを確認してください。

いくつかの言葉

たとえば、ドキュメントからタイトルをコピーしてファイル名に貼り付けると、1つ以上の改行がファイル名自体で終了することがあります。タイトルが改行の直前に使用する必要のあるキーすら含まれている可能性があるので、あまりにも不運な場合があります。

The new art of working on .png
files and other formats.

テストしたい場合は、次のコマンドでこのようなファイル名を作成できます

touch "A file with two lines"$'\n'"and This is the second.png"
touch "The new art of working on .png"$'\n'"files and other formats.png"

単純な/bin/ls *pngは、印刷できない文字の代わりに?を出力します

A file with two lines?and This is the second.png
The new art of working on .png?files and other formats.png

出力をパイプするlsまたはfindのすべてのケースで、現在の行が新しいファイル名、または前のファイル名改行文字の後に続く場合nastyの名前は確かにありますが、それでも正当な名前です。

Shell Parameter-Expansion、${parameter%Word}printfまたはechoの両方のバリアントでのシェルサイクルは機能します [ cuonglm ]、[ Anthon1 ] 。

for f in *.png; do printf "%s\n" "${f%.png}" ; done

Shell Parameter Expansionのmanページから []

$ {parameter%Word}
$ {parameter %% Word}

...展開の結果は、最短一致パターン( ‘%’ケース)または最長一致パターン( ‘%%’ケース)が削除されたパラメーターの値です。

6
Hastur

それで十分でしたか?

ls -1 | sed 's/\.png//g'

または一般的に、これ

ls -1 | sed 's/\.[a-z]*//g'

すべての拡張機能を削除します

5
Rohail Abbas

revを使用:

ls -1 | rev | cut -f 2- -d "." | rev

revはすべての文字列(行)を逆にします。最初の '。'の後にすべてをカットします。 revは残りを逆転させます。

grep 'alma'にしたい場合:

ls -1 | rev | cut -f 2- -d "." | rev | grep 'alma'
3
Tom Solid

ディレクトリに拡張子が.pngのファイルしかないことがわかっている場合は、次のコマンドを実行するだけです:ls | awk -F. '{print $1}'

これは、filename.extensionがあるすべての場所の最初の「フィールド」を返します。

例:

[rsingh@rule51 TESTDIR]$ ls
10.png  1.png  2.png  3.png  4.png  5.png  6.png  7.png  8.png  9.png

[rsingh@rule51 TESTDIR]$ ls | awk -F. '{print $1}'
10
1
2
3
4
5
6
7
8
9
2
rsingh

あなたのコメントによると「拡張子のないすべての名前がリストされているテキストファイルがあります。PHPスクリプトを作成して、テキストファイルとフォルダーを比較して、どのファイルが"がありません:

for file in $(cat yourlist) ; do
  [ -f "${file}.png" ] || {
    echo "$file : listed in yourlist, but missing in the directory"
  }
done
#assumes that filenames have no space...
# otherwise use instead:
#  while IFS= read file ; do ...(same inner loop as above)... ; done < yourlist

そしてその逆:

for file in *.png ; do
  grep "^${file%.png}$" yourlist >/dev/null || {
    echo "$file: present in the directory but not listed in yourlist"
  }
done
#I assume there are no spaces/tabs/? before/after names in 'yourlist'. Change the script accordingly if there are some (or sanitize the list)
2
Olivier Dulac

スーパーレーターが「。」であるlsの出力について、次のフィードを試すことができます。すべてのファイルにname.pngが含まれるため、最初の列を印刷します。
ls | awk -F"." '{print $1}'

1
igiannak

単純なシェル行(ksh、bashまたはzsh、ダッシュではない):

set -- *.png; printf '%s\n' "${@%.png}"

単純な関数(拡張なしから):

ne(){ set -- *.png; printf '%s\n' "${@%.png}"; }

または、指定された拡張子を削除する関数(デフォルトではPNG):

ne(){ ext=${1:-png}; set -- *."$ext"; printf '%s\n' "${@%.${ext}}"; }

使用:

ne jpg

出力がアスタリスクの場合*、その拡張子を持つファイルは存在しません。

1
user79743

ls -l | sed 's/\.png$//'

@roaimaで強調表示されている最も正確な方法です。エスケープされた\.pngがないと、a_png.pngという名前のファイルはa_としてリストされます。

1
aphorise