J'essaie d'écrire un script extrêmement simple dans Ubuntu qui me permettrait de lui transmettre un nom de fichier ou un répertoire, et de pouvoir faire quelque chose de spécifique lorsqu'il s'agit d'un fichier et autre chose lorsqu'il s'agit d'un répertoire. Le problème que je rencontre est lorsque le nom du répertoire, ou probablement des fichiers aussi, contient des espaces ou d’autres caractères d'échappement dans le nom.
Voici mon code de base ci-dessous, et quelques tests.
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ] ; then
echo "$PASSED is a directory";
else
if [ -f "${PASSED}" ]; then
echo "${PASSED} is a file";
else
echo "${PASSED} is not valid";
exit 1
fi
fi
Et voici la sortie:
andy@server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory
andy@server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file
andy@server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid
andy@server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid
Tous ces chemins sont valides et existent.
Cela devrait fonctionner. Je ne sais pas pourquoi c'est un échec. Vous citez vos variables correctement. Que se passe-t-il si vous utilisez ce script avec le double [[
]]
?
if [[ -d $PASSED ]]; then
echo "$PASSED is a directory"
Elif [[ -f $PASSED ]]; then
echo "$PASSED is a file"
else
echo "$PASSED is not valid"
exit 1
fi
Les doubles crochets sont une extension bash à [ ]
. Il n’est pas nécessaire de citer des variables, même si elles contiennent des espaces.
Cela vaut également la peine d'essayer: -e
pour tester si un chemin existe sans tester le type de fichier.
Au moins, écrivez le code sans l'arbre touffu:
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ]
then echo "${PASSED} is a directory";
Elif [ -f "${PASSED}" ]
then echo "${PASSED} is a file";
else echo "${PASSED} is not valid";
exit 1
fi
Quand je mets cela dans un fichier "xx.sh" et crée un fichier "xx sh", et l'exécute, je reçois:
$ cp /dev/null "xx sh"
$ for file in . xx*; do sh "$file"; done
. is a directory
xx sh is a file
xx.sh is a file
$
Étant donné que vous rencontrez des problèmes, vous devez déboguer le script en ajoutant:
ls -l "${PASSED}"
Cela vous montrera ce que ls
pense des noms que vous transmettez au script.
Utiliser -f
et -d
permet d'activer /bin/test
:
F_NAME="${1}"
if test -f "${F_NAME}"
then
echo "${F_NAME} is a file"
Elif test -d "${F_NAME}"
then
echo "${F_NAME} is a directory"
else
echo "${F_NAME} is not valid"
fi
Une solution plus élégante
echo "Enter the file name"
read x
if [ -f $x ]
then
echo "This is a regular file"
else
echo "This is a directory"
fi
MISE À JOUR: J'ai été voté, j'ai donc décidé de réécrire ma réponse, merci pour les commentaires.
Utiliser la commande "fichier" peut être utile pour cela:
#!/bin/bash
check_file(){
if [ -z "${1}" ] ;then
echo "Please input something"
return;
fi
f="${1}"
result="$(file $f)"
if [[ $result == *"cannot open"* ]] ;then
echo "NO FILE FOUND ($result) ";
Elif [[ $result == *"directory"* ]] ;then
echo "DIRECTORY FOUND ($result) ";
else
echo "FILE FOUND ($result) ";
fi
}
check_file ${1}
Exemples de sortie:
$ ./f.bash login
DIRECTORY FOUND (login: directory)
$ ./f.bash ldasdas
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or directory))
$ ./f.bash evil.php
FILE FOUND (evil.php: PHP script, ASCII text)
FYI: les réponses ci-dessus fonctionnent, mais vous pouvez utiliser -s pour vous aider dans des situations étranges en recherchant d'abord un fichier valide:
#!/bin/bash
check_file(){
local file="${1}"
[[ -s "${file}" ]] || { echo "is not valid"; return; }
[[ -d "${file}" ]] && { echo "is a directory"; return; }
[[ -f "${file}" ]] && { echo "is a file"; return; }
}
check_file ${1}
Bon mot
touch bob; test -d bob && echo 'dir' || test -f bob && echo 'file'
le résultat est vrai (0) (dir) ou vrai (0) (fichier) ou faux (1) (ni)