Google グループは Usenet の新規の投稿と購読のサポートを終了しました。過去のコンテンツは引き続き閲覧できます。
表示しない

拡張子を抜いたファイル名を取得したい

閲覧: 1 回
最初の未読メッセージにスキップ

hanajipon

未読、
2003/10/06 10:17:542003/10/06
To:
hanajipon です。
csh で 例えば
foreach i ( `ls -1` )
echo ">>>$i:r<<<"
end

とかすると拡張子を除いたファイル名が表示されますが、
これを bash で行うにはどうしたら良いでしょうか?
---
hanajipon @ mail.goo.ne.jp

SAITO Shukaku

未読、
2003/10/06 21:33:552003/10/06
To:
At Mon, 6 Oct 2003 23:17:54 +0900,

hanajipon wrote:
>
> csh で 例えば
> foreach i ( `ls -1` )
> echo ">>>$i:r<<<"
> end
>
> とかすると拡張子を除いたファイル名が表示されますが、
> これを bash で行うにはどうしたら良いでしょうか?

これでどうでしょう?

for i in `ls -1`; do echo ">>>${i%.*}<<<"; done

///// ------------------------------------------------------------------
-O-O- 斉藤 秀格 (SAITO Shukaku) @ PUGH (Palm Users Group in Hokkaido)
_ mailto:shu...@sai10.nu (ぱふ) http://www.pugh.palm-j.com/

Nakayama Ryu~ji

未読、
2003/10/09 12:07:342003/10/09
To:
Article <blrtil$h0g$1...@nn-os102.ocn.ad.jp> にて、
"hanajipon" <hana...@mail.goo.ne.jp> さん、

> csh で 例えば
> foreach i ( `ls -1` )
> echo ">>>$i:r<<<"
> end
>
> とかすると拡張子を除いたファイル名が表示されますが、
> これを bash で行うにはどうしたら良いでしょうか?

bashの機能を用いた方法は斉藤さんが示されていますので、shellの種類を問
わない方法を。

多くのUNIX系OSではbasenameというコマンドがあり、

echo ">>>"`basename $i`"<<<"

とすることで、拡張子とフルパス・相対パスの場合はディレクトリ部分も除去
できます。ただ、この方法を使うとプロセスを大量に消費しますので、shell
に機能が備わっているときはそちらを使ったほうがいいでしょう。

--
中山隆二
nakayam...@anet.ne.jp

R4000 2.2

未読、
2003/10/10 10:46:112003/10/10
To:
こんばんは、立花@鎌ヶ谷市です。

Nakayama Ryu~ji <nakayam...@anet.ne.jp> writes:

> Article <blrtil$h0g$1...@nn-os102.ocn.ad.jp> にて、
> "hanajipon" <hana...@mail.goo.ne.jp> さん、
>
> > csh で 例えば
> > foreach i ( `ls -1` )
> > echo ">>>$i:r<<<"
> > end
> >
> > とかすると拡張子を除いたファイル名が表示されますが、
> > これを bash で行うにはどうしたら良いでしょうか?

:


> echo ">>>"`basename $i`"<<<"
>
> とすることで、拡張子とフルパス・相対パスの場合はディレクトリ部分も除去
> できます。

上記だと、拡張子は残っちゃいますよね。

echo ">>>"`basename $i | cut -d. -f1`"<<<"

でどうでしょう。
#あ、残したい部分に '.' があるとだめだなぁ

--
ta...@kc5.so-net.ne.jp 立花 晃@鎌ヶ谷市

OOTANI TAKASHI

未読、
2003/10/10 10:56:542003/10/10
To:
Nakayama Ryu~ji <nakayam...@anet.ne.jp> writes:
> bashの機能を用いた方法は斉藤さんが示されていますので、shellの種類を問
> わない方法を。
>
> 多くのUNIX系OSではbasenameというコマンドがあり、
>
> echo ">>>"`basename $i`"<<<"
>
> とすることで、拡張子とフルパス・相対パスの場合はディレクトリ部分も除去

basename で拡張子を除去するには、除去する拡張子を第二パラメータで
指定する必要がありますので、これではだめです。
expr を使って、

echo ">>>"`expr $i : '\(.*\)\.' '|' $i`"<<<"

--
oo

Takashi SHIRAI

未読、
2003/10/10 12:46:392003/10/10
To:
 しらいです。

In article <u4qyiw...@anet.ne.jp>,


Nakayama Ryu~ji <nakayam...@anet.ne.jp> wrote:
>> とかすると拡張子を除いたファイル名が表示されますが、
>> これを bash で行うにはどうしたら良いでしょうか?
>
>bashの機能を用いた方法は斉藤さんが示されていますので、shellの種類を問
>わない方法を。

 ${%} や ${#} は bash 独自仕様ではなく POSIX 規格なので、他
にも ash や ksh などに実装されていますね。


>多くのUNIX系OSではbasenameというコマンドがあり、
>
>echo ">>>"`basename $i`"<<<"

 find ならともかく、ls -1 の出力に対して basename が有効と
なるような局面は想像だに出来ないんですけど、一体何と勘違いさ
れたんでしょうか?
 今回のような用途だと普通は expr でしょうかね。sed とか awk
とか perl とかの方が手っ取り早いかも。


>とすることで、拡張子とフルパス・相対パスの場合はディレクトリ部分も除去
>できます。ただ、この方法を使うとプロセスを大量に消費しますので、shell
>に機能が備わっているときはそちらを使ったほうがいいでしょう。

 basename 自身よりも `` の方がコストが高いですね。そういう
意味では `ls -1` している時点で無駄なので、「foreach i (*)」
や「for i in *」で構わないと思います。`ls -1a` なら wildcard
での置換えはちょっと tricky になりますけど。
 コストを極力抑え、Bourne shell 標準の機能だけで実現させる
ならばこんな感じでしょうかね。

---- Cut Here ----
#!/bin/sh

for i in *; do
case "${i}" in
'*')
break
;;
esac
OIFS=${IFS}
IFS=.
set -- ${i}
IFS=${OIFS}
i=$1
while :; do
shift
case "$#" in
0|1)
break
;;
*)
i=${i}.$1
;;
esac
done
echo ">>>"${i}"<<<"
done
---- Cut Here ----

 最後の echo(1) 以外 fork も exec もしない筈。最近の実装で
は echo すら builtin だったりするので、それだと全部 shell の
中だけで閉じるかな。

# test で済むところを case で書くと見づらいだけですが :-)

--
しらい たかし

Nakayama Ryu~ji

未読、
2003/10/10 12:51:102003/10/10
To:
Article <bm6gno$et9$1...@news01dh.so-net.ne.jp> にて、
ta...@kc5.so-net.ne.jp (R4000 2.2) さん、

> Nakayama Ryu~ji <nakayam...@anet.ne.jp> writes:
>
>> Article <blrtil$h0g$1...@nn-os102.ocn.ad.jp> にて、
>> "hanajipon" <hana...@mail.goo.ne.jp> さん、
>>
>> > csh で 例えば
>> > foreach i ( `ls -1` )
>> > echo ">>>$i:r<<<"
>> > end
>> >
>> > とかすると拡張子を除いたファイル名が表示されますが、
>> > これを bash で行うにはどうしたら良いでしょうか?
> :
> > echo ">>>"`basename $i`"<<<"
>>
>> とすることで、拡張子とフルパス・相対パスの場合はディレクトリ部分も除去
>> できます。
>
> 上記だと、拡張子は残っちゃいますよね。

えっ…あ、ホントだ。すみません、ろくに確認せずに記事を書いてしまいまし
た。

> echo ">>>"`basename $i | cut -d. -f1`"<<<"
>
> でどうでしょう。
> #あ、残したい部分に '.' があるとだめだなぁ

他お二方(11日2時時点)もご指摘ありがとうございます。

勘違いというか、単なるボケです。:-)

--
中山隆二
nakayam...@anet.ne.jp

IIJIMA Hiromitsu

未読、
2003/10/10 13:30:352003/10/10
To:
いいじまです。

> # test で済むところを case で書くと見づらいだけですが :-)

手元の bash だと test や [ も built-in です :-)

ちなみにバージョンは

% bash --version
GNU bash, version 2.05b.0(1)-release (i386-portbld-freebsd4.7)
Copyright (C) 2002 Free Software Foundation, Inc.

ですけど、私が bash を触るようになったころ(っていってもつい最近ですが)
は既に test/[ は built-in。

========================================================================
飯嶋 浩光 / でるもんた・いいじま http://www.ht.sakura.ne.jp/~delmonta/
IIJIMA Hiromitsu, aka Delmonta mailto:delm...@ht.sakura.ne.jp

tesi...@mtf.biglobe.ne.jp

未読、
2003/10/11 4:19:422003/10/11
To:
shi...@unixusers.net (Takashi SHIRAI) writes:

>  basename 自身よりも `` の方がコストが高いですね。そういう
> 意味では `ls -1` している時点で無駄なので、「foreach i (*)」
> や「for i in *」で構わないと思います。

* で ARG_MAX越えたりしないですか?
---------------------------------------------------------------------
tesi...@mtf.biglobe.ne.jp

MAEDA Atusi

未読、
2003/10/11 9:27:282003/10/11
To:
tesi...@mtf.biglobe.ne.jp (tesi...@mtf.biglobe.ne.jp) writes:

> > 意味では `ls -1` している時点で無駄なので、「foreach i (*)」
> > や「for i in *」で構わないと思います。
>
> * で ARG_MAX越えたりしないですか?

/bin/ls -1 | sed -e 's/\(.*[^.].*\)\.[^.]*$/\1/' -e 's/.*/>>> \0 <<</'

でどうでしょう.forでループするより速いみたいです.

前田敦司

Takashi SHIRAI

未読、
2003/10/11 10:06:092003/10/11
To:
 しらいです。

In article <bm8er8$1e1$1...@bgsv5647.tk.mesh.ad.jp>,


tesi...@mtf.biglobe.ne.jp <tesi...@mtf.biglobe.ne.jp> wrote:
>>  basename 自身よりも `` の方がコストが高いですね。そういう
>> 意味では `ls -1` している時点で無駄なので、「foreach i (*)」
>> や「for i in *」で構わないと思います。
>
>* で ARG_MAX越えたりしないですか?

 ARG_MAX って何の値だかご存知ですか?* の展開は shell 自身
のお仕事ですよ。

 Bourne shell の中で閉じてて exec していない訳ですから、も
し制限があるとするならば ARG_MAX ではなくて Bourne shell の
内部で設けられた制限だけになる筈です。
 確か Bourne shell の実装では malloc() で確保していた筈なの
で、制限となるのは ARG_MAX とか Bourne shell で定義したある
種の定数値とかではなく、むしろ RLIMIT_DATA の方でしょうね。

 ARG_MAX の制限と比べてどちらが厳しいかですけど、E2BIG を返
すのは execve() ですので、もし malloc() し切れない程の数があ
ったとしたら、execve() に渡す以前に shell の内部処理で失敗す
る筈。
 一般論としても、普通は多分 ARG_MAX の制限の方が先に来ると
思います。ARG_MAX ってせいぜい K order ですが RLIMIT_DATA の
方は MB order ですよね。
 filename の長さにも依存しますが、MAXNAMLEN が KB order の
環境で目一杯使い果たした状況でも無い限りは ARG_MAX の方が先
に上限に達する筈です。

 尤も、RLIMIT_DATA の方も決して上限に達しない保証はない訳な
ので、もしそこまで偏執狂になるのでしたら、ここで初めて ls -1
の出番ですね。
 それでも `` なんか使ったら同様に RLIMIT_DATA の制限に引っ
かかりますから、ls の出力を temporary file に落とす必要があ
るでしょうね。
 ls した結果が何 MB にもなるような状況ってなかなか想像しづ
らいので、何が起こるか保証の限りではありませんけど、pipe に
通して処理させるのでも可能かも知れません。
 pipe が使えたとしたら、一行目を「ls -l | while read i; do」
に変えるだけで対応可能だと思います。但し、filename に「\」を
含んでたりすると話がややこしくなりますが。

--
しらい たかし

Takashi SHIRAI

未読、
2003/10/11 10:16:502003/10/11
To:
 しらいです。

In article <3F86ECBB...@ht.sakura.ne.jp>,


IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> wrote:
>いいじまです。

>> # test で済むところを case で書くと見づらいだけですが :-)
>
>手元の bash だと test や [ も built-in です :-)

 話は既に bash への依存性を無くすにはという仮定の話になって
いるんですけど。bash ならば ${i%.*} で解決済み。

 尤も、Bourne shell も後期は test を builtin で用意していま
す。4.3BSD の頃は /bin/test でしたが、S.Bourne が SunOS に実
装した頃には test を内部で実装していました。
 なので、その頃に各ベンダーから出ていた UNIX では、この後期
版の拡張 Bourne shell が実装されていたと思います。

# それ以降の UNIX になると、ash や ksh に取って代わられて、
#Bourne shell 自体が載ってなかったりします。流石に S.Bourne
#を抱えていた Sun では未だに Solaris に載せていますけど。


>ですけど、私が bash を触るようになったころ(っていってもつい最近ですが)
>は既に test/[ は built-in。

 bash は Bourne shell と比べて随分後ですので、これには最初
から test が builtin で実装されていた筈です。

--
しらい たかし

Takashi SHIRAI

未読、
2003/10/11 10:30:192003/10/11
To:
 しらいです。

In article <m365iv5...@maedapc.cc.tsukuba.ac.jp>,


MAEDA Atusi <ma...@cc.tsukuba.ac.jp> wrote:
>/bin/ls -1 | sed -e 's/\(.*[^.].*\)\.[^.]*$/\1/' -e 's/.*/>>> \0 <<</'
>
>でどうでしょう.forでループするより速いみたいです.

 速度だけを問題にするんでしたら、shell script でしこしこ書
かれたものは parsing の手間がかかるので決して勝ち目はないと
思います。
 wild card の展開も結構手間になるので、「ls -1」を「ls -1 *」
に変えただけでも遅くなったりするんじゃないでしょうかね。
 fork & exec にコストがかかると言っても、loop の外で行なう
分には大勢に影響無いでしょうから、速度重視ならば各種 script
言語が最適解でしょう。

# 私が挙げたのは飽くまでも「shell の種類を問わない方法」な
#ので、外部コマンドの使用は最低限に抑えました。single user
#mode で使えるとかいうメリットは最近意味ないかなー。

--
しらい たかし

hanajipon

未読、
2003/10/15 3:45:402003/10/15
To:
hanajipon@元ネタ発信者です。

"Takashi SHIRAI" <shi...@unixusers.net> wrote in message
news:bm6nnp$dbg$1...@nsvn01.zaq.ne.jp...


>  しらいです。
>
> In article <u4qyiw...@anet.ne.jp>,
> Nakayama Ryu~ji <nakayam...@anet.ne.jp> wrote:
> >> とかすると拡張子を除いたファイル名が表示されますが、
> >> これを bash で行うにはどうしたら良いでしょうか?
> >
> >bashの機能を用いた方法は斉藤さんが示されていますので、shellの種類を問
> >わない方法を。
>
>  ${%} や ${#} は bash 独自仕様ではなく POSIX 規格なので、他
> にも ash や ksh などに実装されていますね。

#出張でしばらく離れていたら、いつのまにかスレッドが巨大になってる・・・。

またまた初歩的な質問かもしれず、恐縮ですが、この
${%} や ${#} の表記方法の意味をリファレンスで引くには何が手っ取り早いでしょ
うか?
または、このことを何と言うのでしょうか?

man bash をしたのですが、見つけきれませんでした。

Fujii Hironori

未読、
2003/10/15 3:55:522003/10/15
To:
At Wed, 15 Oct 2003 16:45:40 +0900,

hanajipon wrote:
>
> またまた初歩的な質問かもしれず、恐縮ですが、この
> ${%} や ${#} の表記方法の意味をリファレンスで引くには何が手っ取り早いでしょ
> うか?
> または、このことを何と言うのでしょうか?
>
> man bash をしたのですが、見つけきれませんでした。

もとは POSIX だそうですが、とりあえず
手許のbash(1)から引用

Parameter Expansion

(...)

${parameter#word}
${parameter##word}
The word is expanded to produce a pattern just as in pathname expansion. If the pattern
matches the beginning of the value of parameter, then the result of the expansion is the
expanded value of parameter with the shortest matching pattern (the ``#'' case) or the
longest matching pattern (the ``##'' case) deleted. If parameter is @ or *, the pattern
removal operation is applied to each positional parameter in turn, and the expansion is
the resultant list. If parameter is an array variable subscripted with @ or *, the pat-
tern removal operation is applied to each member of the array in turn, and the expansion
is the resultant list.

${parameter%word}
${parameter%%word}
The word is expanded to produce a pattern just as in pathname expansion. If the pattern
matches a trailing portion of the expanded value of parameter, then the result of the
expansion is the expanded value of parameter with the shortest matching pattern (the
``%'' case) or the longest matching pattern (the ``%%'' case) deleted. If parameter is
@ or *, the pattern removal operation is applied to each positional parameter in turn,
and the expansion is the resultant list. If parameter is an array variable subscripted
with @ or *, the pattern removal operation is applied to each member of the array in
turn, and the expansion is the resultant list.

---
藤井宏憲

Takashi SHIRAI

未読、
2003/10/15 9:41:272003/10/15
To:
 しらいです。

In article <87oewjq6if.wl%fu...@chi.its.hiroshima-cu.ac.jp>,
Fujii Hironori <fu...@chi.its.hiroshima-cu.ac.jp> wrote:
>もとは POSIX だそうですが、とりあえず

 ${#} や ${%} は確かに POSIX 規格ですが、POSIX は何もないと
ころから作られている訳ではないので、POSIX 規格には大概その元
となる実装が存在します。大抵は SystemV 系ですね。
 という訳で、${#}/${%} も多分 SystemV 標準 shell である Korn
shell に由来していると思います。だとすると、参照すべきはこの
辺りかと。
http://www.cs.princeton.edu/~jlk/kornshell/doc/man88.html

 「Parameter Substitution.」の項目で後ろの方に載ってます。

--
しらい たかし

NODA Takashi

未読、
2003/10/17 11:39:282003/10/17
To:
のだです。

shi...@unixusers.net (Takashi SHIRAI) writes:
> In article <87oewjq6if.wl%fu...@chi.its.hiroshima-cu.ac.jp>,
> Fujii Hironori <fu...@chi.its.hiroshima-cu.ac.jp> wrote:
>>もとは POSIX だそうですが、とりあえず
>
>  ${#} や ${%} は確かに POSIX 規格ですが、POSIX は何もないと
> ころから作られている訳ではないので、POSIX 規格には大概その元
> となる実装が存在します。大抵は SystemV 系ですね。

> http://www.cs.princeton.edu/~jlk/kornshell/doc/man88.html

SysV系の歴史は追えなかったのですが、BSD系では4.4BSD時代に実装されているようです。

http://www.freebsd.org/cgi/man.cgi?query=sh&apropos=0&sektion=0&manpath=4.4BSD+Lite2&format=html

上記の用に4.4BSD Lite2 の sh のマニュアルには該当の記述があります
が、その後リリースされたNetBSD1.0のshのマニュアルの中では
(UNIMPLEMENTED IN 4.4alpha)
と 4.4alpha では実装されていないことが明記されています。

▼△ のだたかし (NODA Takashi)
▽▲ mailto:no...@mb.neweb.ne.jp

新着メール 0 件