challenge 自分自身のファイル名を知る方法

自分自身のファイル名を知る方法を示してください。

ビルド後のファイルが、hogehoge.exeであれば、
”hogehoge.exe”が表示されるようなプログラムを書いてください。
スクリプト言語でも同様です。

ファイル名が変更されたらそれに追従するようにしてください。

Posted feedbacks - Nested

Flatten Hidden
1
2
3
import sys

print sys.argv[0]

どちらが欲しいかはケースバイケースだと思うのですが、実行したファイル名ではなくライブラリスクリプト自身のファイル名が欲しい場合には __file__ を使います。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#/////////////
# a.py

import b

#/////////////
# b.py

import sys

print __file__    # ..../b.py
print sys.argv[0] # ..../a.py
同案多数でしょうが、ruby の場合 __FILE__ 変数に自分自身のファイル名が格納されています。 irb では nil が、ruby -e '...' では "-e" が格納されます。
1
puts __FILE__
1
2
3
4
5
6
7
#include <libgen.h>
#include <stdio.h>

int main( int argc, char *argv[] ){
   printf("%s\n", basename(argv[0]) );
   return 0;
}

sayが使いたかっただけ。

1
2
3
4
5
use 5.10;
use feature qw/say/;
use File::Basename;

say basename $0;

間違い訂正(Perl 5.100ってなんだ)

1
2
3
4
1c1
< use 5.10;
---
> use 5.010;
1
puts [file dirname [info script]]
1
WSH.echo(WSH.scriptName);
1
System launchScript print
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine( Process.GetCurrentProcess().ProcessName );
        }
    }
}

Squeak Smalltalk はイメージベースなので、使用中の仮想イメージファイル名でご容赦を。

1
2
FileDirectory localNameFor: SmalltalkImage current imageName
'#=> Squeak3.9-final-7067.image'
1
2
3
import System.Environment

main = getProgName >>= putStrLn

Javaではもともとクラス名=ファイル名なので、パスを含めてURLで表示してみました。

1
2
3
4
5
6
7
8
9
package doukaku;

public class MyFilename {
   public static void main(String[] args) {
      System.out.println(
          MyFilename.class.getClassLoader().getResource(
              MyFilename.class.getName().replaceAll("\\.","/")+".class"));
   }
}
シェルスクリプトでは #5725が参考になると思います。

ちなみに、以下のOSで動作することを確認。

  AIX     (4.3)
  HP-UX   (11.00)
  Linux   (2.4)
  Solaris (5.5)

#  Solarisでも/usr/xpg4/bin/shを使用すれば、パターン照合演算子に対応しているので
# 動作します。
1
2
3
<?php
print __FILE__;
?>
1
print_endline Sys.executable_name;;
1
2
3
begin
  Writeln(ParamStr(0));
end.
1
2
3
4
// ファイルのパス
コマンドライン[0]を表示
// なでしこインタプリタのパス
ナデシコランタイムパスを表示
Includeされる側と、実行側で取得方法が異なると思います。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php 
//状況によって違うと思います。
//実行中のファイル名は
echo $_SERVER['PHP_SELF'];
//ソースコードの現在位置のファイル名は
echo __FILE__

if (  __FILE__ == $_SERVER["PHP_SELF"] ){
//今このファイルが実行されている。
echo "this";
}
 #3301は拡張子を含まない例なので、拡張子を含むファイル名を取得する方法を検証しま
した。なお、「長いファイル名」とは「ロングファイルネーム( LFN)」のことを、「短い
ファイル名」とはいわゆる「 8.3形式( SFN)」のことを指していると思ってください。

  e.g.
    C:\>"C:\Documents and Settings\kshibamo\デスクトップ\どう書く?org Beta.bat"
    長いファイル名 : どう書く?org Beta.bat
    短いファイル名 : どう書~1.BAT

Windows NT, 2000, XP, 2003で動作確認したところ、パス文字列にマルチバイトが含まれ
る場合に限り、Windows NTと2000では短いファイル名を取得することができませんでした。

  e.g.
    Windows NTの場合
      短いファイル名 : org Beta

    Windows 2000の場合
      短いファイル名 : (何も出力されない)
1
2
3
4
5
6
7
:: どう書く?org Beta.bat
@echo off
  setlocal
    echo 長いファイル名 : %~nx0
    echo 短いファイル名 : %~nxs0
  endlocal
goto :EOF

#5797 のコメントでこのお題は全てなのですが、static メソッドからは自分自身のクラス名が取れない事が気になって、強引に外部からクラス名を取る事を試みてみました。

コマンドラインを取得して起動コマンドからクラス名を取得する戦略です。ただし、Javaからは生のコマンドラインが取れないため、ps コマンドを外部起動して ps コマンドの ppid から自分自身の pid を取得し、コマンドラインを求めています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.*;
import java.util.*;
import java.util.regex.*;

public class Sample {
    public static final Pattern psPattern = Pattern.compile("ps -Awwo pid");
    public static void main(String[] args) throws Exception { 
        Runtime rt = Runtime.getRuntime();
        Process p = rt.exec(new String[]{"ps", "-Awwo", "pid,ppid,command"});
        BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line, javaPid = "";
        HashMap<String, String> pMap = new HashMap<String, String>();
        while ((line = r.readLine()) != null) {
            String[] token = line.split("\\s+", 4);
            pMap.put(token[1], token[3]);
            if (psPattern.matcher(token[3]).find()) {
                javaPid = token[2];
            }
        }
        String[] token = pMap.get(javaPid).split("\\s+");
        System.out.println(token[1] + ".class");
    }
}

#5812 はOSに依存します(ちなみに、Mac OS Xで確認しました)。クラス名を得るだけであれば、別にコマンドラインを取得する必要はないので、もっと単純な方法も提示しておきます。

1
2
3
4
5
6
7
public class Sample2 {
    public static void main(String[] args){ 
        Exception ex = new Exception();
        StackTraceElement[] st = ex.getStackTrace();
        System.out.println(st[0].getClassName() + ".class");
    }
}

StackTrace が欲しいなら、Exception を作るより、Thread.currentThread().getStackTrace() を使う方がいいですよ。

ちょっと意地悪かもしれませんが、java -jar foo.jarで実行された場合、私の理解ではfoo.jarが正解だと思います。他の答えではわからないので、一番答えに近いのはこれかなと思います。

PostScript といいつつ、 Ghostscript 依存です。 まっとうな PostScript では自分自身のファイルは currentfile で取得して読み出しできるのですが、PostScript Level 2で拡張された「名前付きファイル」の名前のほうを参照する方法が無さげです。Ghostscript の名前 変換オペレータ の .filename を使用しています。

1
2
%!PS
currentfile .filename { = } if
1
WSH.Echo(WSH.ScriptName);
1
print $0;

フルパス

1
print $ENV{PWD}."/$0";

Windows版です

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] ) {
    char command[BUFSIZ];
    sprintf(command, "dir /B \"%s\"", argv[0]);
    system(command);
    return 0;
}
1
2
3
4
5
6
7
8
9
import std.stdio;
import std.path;

void main(string[] args){
    writefln(getBaseName(args[0]));

    // >= 2.006
    // writefln(basename(args[0]));
}

99yenさんのものだとパスも表示されてしまうので。

1
コマンドライン[0]からファイル名抽出を表示

ああ、本当ですね。ありがとうございます。

1
2
3
(define (main args)
  (print (car args))
  0)

コマンドラインから

1
print $argv[0];

質問です。 ln -sの影響を受けるのでしょうか?

http://jr0bak.homelinux.net/~imai/linux/embedded_beginner-5.html#ss5.2

ロード中のファイルの pathname が *load-pathname* に入っています。 ファイル名を文字列として取得するには file-namestring を使います。

1
(print (file-namestring *load-pathname*))

ファイル名だけ取得する場合。ExtractFilenameでファイル名だけ取り出します。

1
2
3
4
5
6
uses
  SysUtils;

begin
  Writeln(ExtractFilename(ParamStr(0)));
end.
escript で。
1
2
#!/usr/bin/env escript
main(_) -> io:fwrite("~s~n", [escript:script_name()]).
1
print(arg[0])
もっといい方法がありそう。。。

実行結果
$erl -noshell -run my bin -s init stop
my.beam
$erl -noshell -run my src -s init stop
my.erl
1
2
3
4
5
6
-module(my).
-export([src/0,bin/0]).
src()->
    io:format("~s~n",[filename:basename(?FILE)]).
bin()->
    io:format("~s~n",[filename:basename(code:which(?MODULE))]).

蛇足。

1
2
3
4
import sys
import os

print os.path.split(sys.argv[0])[1]
他の投稿を見るに、題意を読み違えてたようだ。
でも敢えて投稿。

実行後、何らかの入力を行う度にファイル名を出力する。
下の実行例は 3 回目の入力を行う前に
$ mv ownname.scm hoge.scm
とリネームしている例。
実行例:
$ ./ownname.scm 
?
ownname.scm
?
ownname.scm
?
hoge.scm
?
hoge.scm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/gosh

(use gauche.selector)
(use gauche.process)
(use file.util)

(define (main args)
  (let ((ino (number->string (file-ino *program-name*)))
       (selector (make <selector>)))
    (selector-add! selector 
                   (standard-input-port)
                   (lambda (port flag)
                     (if (not (eof-object? (read-line port)))
                         (let1 p (run-process (list "find" "./" "-inum" ino) :output :pipe)
                           (display (sys-basename (read-line (process-output p))))
                           (newline))
                         (exit)))
                   '(r))
    (do () (#f) (selector-select selector))))
今のところWindowsにのみ対応しています。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

/* The backslash is 0x5C in ASCII. */
#ifdef WIN32
#define PASS_SLICE 0x5C
#define HAVE_SLICE TRUE
#endif

#ifdef HAVE_SLICE
#include <string.h>
#endif

int main(int argc, char* argv[])
{
    char *point;

#ifdef HAVE_SLICE
    point = strrchr(argv[0], PASS_SLICE);
#else
    point = NULL;
#endif

    printf("%s\n", (point == NULL) ? argv[0] : ++point);

    return 0;
}

開発環境: Mac OS X 10.5.2, Xcode 3.1 (Beta)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    NSLog( [[[NSBundle mainBundle] executablePath] lastPathComponent] );
    
    [pool drain];
    return 0;
}
fumokmm氏のコードが参考になりました。 ThrowableのstackTraceからエラー処理でなく情報を抜き取る技は、いろいろ応用が効きそうです。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def getFileName() {
    def the_thisClassName = getClass().getName()
    def the_inThisObject = new Throwable().getStackTrace().findAll     {
            the_stackTraceElement ->
            the_thisClassName.equals(the_stackTraceElement.getClassName())
        }
    return the_inThisObject[1].getProperties().fileName
}

println getFileName()
windows 用のコンソール版の場合です。
1
exit echo >1{ARGV

Index

Feed

Other

Link

Pathtraq

loading...