
たとえば、以下の出力のようなファイルがたくさんあります。すべての一意のファイル名のリストを取得しようとしていますが、「-」の右側の文字は無視します。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 の解析を回避する find / 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))