ファイル名の一部のみに基づいて一意のファイルを一覧表示します。

ファイル名の一部のみに基づいて一意のファイルを一覧表示します。

たとえば、以下の出力に似た複数のファイルがあり、すべての一意のファイル名のリストを取得しようとしますが、「-」の右側の文字は無視されます。いくつかのバリエーションを試しましたが、ls -la | grep ....- | sort --unique必要な結果が得られませんでした。

4855-00160880.psi
4855-00160980.ps
4855-00160980.psi
5355-00160880.ps
5355-00160880.psi
5355-00160980.ps
5355-00160980.psi
5855-00160880.ps
5855-00160880.psi
5855-00160980.ps
5855-00160980.psi
5855-00160A80.ps
5855-00160A80.psi

理想的には、出力を次のように表示したいと思います。

4855
5355
5855

答え1

~からあなたは本当に分析したくないls、これによりトリックを実行できます。

find . -type f -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u

答え2

これはどうですか?

printf "%-4.4s\n" ????-* | uniq

シェルはワイルドカード文字をアルファベット順に拡張し、結果をに引数として渡しますprintf。書式文字列は各引数を4文字に切り捨て、改行文字を追加します。今残っているのは、隣接する重複エントリを削除することです。

ハイフンの前の桁はわかりませんが、アイデアがある場合はいくつかの候補を繰り返すことができます。

for expr in '??' '???' '????' '?????'  # Quoted (!)
do
    printf "%-${#expr}.${#expr}\n" $expr-* |  # Unquoted!
    uniq
done

これはBashのみを使用します。パラメータ拡張 $[#var}取得した文字列の長さです$var

ループの初期化で拡張を避けるためにワイルドカードを引用し、ループ内で引用されていない変数を使用するためのヒントに注意してください(ほとんどの場合は不可能です)。

答え3

-type f偽の結果を避けるために、DopeGhotiの答えに追加する価値があります.

find . -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
.
4855
5355
5855
find . -maxdepth 1 -type f -exec basename "{}" \; | cut -d'-' -f1 | sort -u
4855
5355
5855
$

元の試みと同じままにするには、これを使用できます(解析するので良いことではありませんls!)

ls -1 | grep ^....-  | cut -c1-4 | sort --unique

Awkベースのソリューション、まだlsを解析しています

ls -1 | awk -F- '{print $1}' | sort --unique

ls出力はすでにソートされているため、各場合にソートは必要ありませんuniq

ls -1 | awk -F- '{print $1}' | uniq

sedベースのソリューション

ls -1 | sed 's/-.*//' | uniq

ls 解析を避けるためのソリューションを探す/sed

find . -type f -printf "%f\n" | sed 's/-.*//g' | sort --unique

「-」の前に常に4桁の数字が来ると、とてもエレガントです。

find . -type f -printf "%.4f\n" | sort -u

答え4

そしてzsh

myfiles=(*-*(.))
print -rl -- ${(u)myfiles[@]%%-*}

これにより、配列に1つ以上のダッシュが含まれるすべての一般的なファイル名が保存されます。次に、配列内の各要素のパラメータ拡張を使用して、最初のダッシュとそれ以降のすべての項目を削除します。重複した要素はフラグによって削除されます(u)
隠しファイルも選択するには、次のようにします。myfiles=(*-*(.D))

関連情報