Ich frage mich, wie ich am einfachsten überprüfen kann, ob ein Programm mit bash ausführbar ist, ohne es auszuführen. Es sollte zumindest prüfen, ob die Datei Ausführungsrechte hat und dieselbe Architektur aufweist (z. B. keine ausführbare Windows-Datei oder eine andere nicht unterstützte Architektur, nicht 64 Bit, wenn das System 32 Bit hat, ...) wie das aktuelle System.
78
file
run für diese Dateien zu überprüfen ?Antworten:
Schauen Sie sich die verschiedenen Testoperatoren an (dies gilt für den Testbefehl selbst, aber die integrierten BASH- und TCSH-Tests sind mehr oder weniger gleich).
Sie werden feststellen,
-x FILE
dass FILE existiert und die Berechtigung zum Ausführen (oder Suchen) erteilt wurde .BASH, Bourne, Ksh, Zsh Script
if [[ -x "$file" ]] then echo "File '$file' is executable" else echo "File '$file' is not executable or found" fi
TCSH- oder CSH-Skript:
if ( -x "$file" ) then echo "File '$file' is executable" else echo "File '$file' is not executable or found" endif
Um die zu bestimmen Art von Datei es sich handelt, versuchen Sie die Datei - Befehl. Sie können die Ausgabe analysieren, um genau zu sehen, um welchen Dateityp es sich handelt. Word 'o Warnung : Manchmal
file
wird mehr als eine Zeile zurückgegeben. Folgendes passiert auf meinem Mac:$ file /bin/ls /bin/ls: Mach-O universal binary with 2 architectures /bin/ls (for architecture x86_64): Mach-O 64-bit executable x86_64 /bin/ls (for architecture i386): Mach-O executable i386
Der
file
Befehl gibt je nach Betriebssystem unterschiedliche Ausgaben zurück. Das Wortexecutable
wird jedoch in ausführbaren Programmen enthalten sein, und normalerweise wird auch die Architektur angezeigt.Vergleichen Sie das Obige mit dem, was ich auf meiner Linux-Box bekomme:
$ file /bin/ls /bin/ls: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), stripped
Und eine Solaris-Box:
In allen drei, werden Sie das Wort sehen
executable
und die Architektur (x86-64
,i386
oderSPARC
mit32-bit
).Nachtrag
Auf den ersten Blick könnten Sie in BASH so etwas tun:
if [ -x "$file" ] && file "$file" | grep -q "Mach-O" then echo "This is an executable Mac file" elif [ -x "$file" ] && file "$file" | grep -q "GNU/Linux" then echo "This is an executable Linux File" elif [ -x "$file" ] && file "$file" | grep q "shell script" then echo "This is an executable Shell Script" elif [ -x "$file" ] then echo "This file is merely marked executable, but what type is a mystery" else echo "This file isn't even marked as being executable" fi
Grundsätzlich führe ich den Test aus. Wenn dies erfolgreich ist, überprüfe ich die Ausgabe des
file
Befehls. Diegrep -q
Mittel drucken keine Ausgabe, sondern verwenden den Exit-Code von grep, um zu sehen, ob ich die Zeichenfolge gefunden habe. Wenn Ihr System nicht benötigt,grep -q
können Sie es versuchengrep "regex" > /dev/null 2>&1
.Auch hier kann die Ausgabe des
file
Befehls von System zu System variieren. Sie müssen daher überprüfen, ob diese auf Ihrem System funktionieren. Außerdem überprüfe ich das ausführbare Bit. Wenn eine Datei eine binäre ausführbare Datei ist, das ausführbare Bit jedoch nicht aktiviert ist, ist sie nicht ausführbar. Dies ist möglicherweise nicht das, was Sie wollen.quelle
[[
oder nur[
?[
einen externen Befehl und keinen eingebauten Shell-Befehl. Es befindet sich normalerweise im/bin
Verzeichnis. Es ist ein Alias für dentest
Befehl.Es scheint, dass niemand bemerkt hat, dass der
-x
Operator die Datei mit dem Verzeichnis nicht unterscheidet.Um eine ausführbare Datei genau zu überprüfen, können Sie sie verwenden
[[ -f SomeFile && -x SomeFile ]]
quelle
Außerdem scheint niemand den Operator -x auf Symlinks bemerkt zu haben. Ein Symlink (Kette) zu einer regulären Datei (nicht als ausführbar klassifiziert) besteht den Test nicht.
quelle
Testen von Dateien, Verzeichnissen und Symlinks
Die hier angegebenen Lösungen schlagen entweder in Verzeichnissen oder in Symlinks (oder in beiden) fehl. Unter Linux können Sie Dateien, Verzeichnisse und Symlinks testen mit:
if [[ -f "$file" && -x $(realpath "$file") ]]; then .... fi
Unter OS X sollten Sie in der Lage sein, Coreutils mit Homebrew zu installieren und zu verwenden
grealpath
.Definieren eines
isexec
FunktionSie können der Einfachheit halber eine Funktion definieren:
isexec() { if [[ -f "$1" && -x $(realpath "$1") ]]; then true; else false; fi; }
Oder einfach
isexec() { [[ -f "$1" && -x $(realpath "$1") ]]; }
Dann können Sie testen mit:
if `isexec "$file"`; then ... fi
quelle
return true
stattecho true
?]]; }
nicht sicher, wie Sie dieses verpasst haben). Und obwohl es die Funktionalität nicht ändert, brauchen Sie nicht einmal die Häkchen in derif
Anweisung :) (I. Vermutlich macht es das Hervorheben anders, kein anderer Unterschied, wenn die RückgabestatusUm zu testen, ob für eine Datei selbst
ACL_EXECUTE
in einem der Berechtigungssätze (Benutzer, Gruppe, andere) ein Bit gesetzt ist, unabhängig davon, wo sie sich befindet, i. e. Verwenden Sie auch auf einem tmpfs mit der Option noexec ,stat -c '%A'
um die Berechtigungszeichenfolge abzurufen , und überprüfen Sie dann, ob sie mindestens einen einzelnen "x" -Buchstaben enthält:if [[ "$(stat -c '%A' 'my_exec_file')" == *'x'* ]] ; then echo 'Has executable permission for someone' fi
Der rechte Teil des Vergleichs kann geändert werden, um spezifischeren Fällen zu entsprechen, z. B. um
*x*x*x*
zu prüfen, ob alle Arten von Benutzern die Datei ausführen können sollten, wenn sie auf einem mit der Option exec bereitgestellten Volume abgelegt wird .quelle
Dies ist möglicherweise nicht so offensichtlich, aber manchmal ist es erforderlich, die ausführbare Datei zu testen, um sie ohne einen externen Shell-Prozess ordnungsgemäß aufzurufen:
function tkl_is_file_os_exec() { [[ ! -x "$1" ]] && return 255 local exec_header_bytes case "$OSTYPE" in cygwin* | msys* | mingw*) # CAUTION: # The bash version 3.2+ might require a file path together with the extension, # otherwise will throw the error: `bash: ...: No such file or directory`. # So we make a guess to avoid the error. # { read -r -n 4 exec_header_bytes 2> /dev/null < "$1" || { [[ -x "${1%.exe}.exe" ]] && read -r -n 4 exec_header_bytes 2> /dev/null < "${1%.exe}.exe" } || { [[ -x "${1%.com}.com" ]] && read -r -n 4 exec_header_bytes 2> /dev/null < "${1%.com}.com" } } && if [[ "${exec_header_bytes:0:3}" == $'MZ\x90' ]]; then # $'MZ\x90\00' for bash version 3.2.42+ # $'MZ\x90\03' for bash version 4.0+ [[ "${exec_header_bytes:3:1}" == $'\x00' || "${exec_header_bytes:3:1}" == $'\x03' ]] && return 0 fi ;; *) read -r -n 4 exec_header_bytes < "$1" [[ "$exec_header_bytes" == $'\x7fELF' ]] && return 0 ;; esac return 1 } # executes script in the shell process in case of a shell script, otherwise executes as usual function tkl_exec_inproc() { if tkl_is_file_os_exec "$1"; then "$@" else . "$@" fi return $? }
myscript.sh :
#!/bin/bash echo 123 return 123
In Cygwin :
> tkl_exec_inproc /cygdrive/c/Windows/system32/cmd.exe /c 'echo 123' 123 > tkl_exec_inproc /cygdrive/c/Windows/system32/chcp.com 65001 Active code page: 65001 > tkl_exec_inproc ./myscript.sh 123 > echo $? 123
Unter Linux :
> tkl_exec_inproc /bin/bash -c 'echo 123' 123 > tkl_exec_inproc ./myscript.sh 123 > echo $? 123
quelle