Script shell pour créer un fichier s'il n'existe pas?

20

J'ai besoin de créer un script shell qui vérifie la présence d'un fichier et s'il n'existe pas, le crée et passe à la commande suivante, ou passe simplement à la commande suivante. Ce que j'ai ne fait pas ça.

#!/bin/bash

# Check for the file that gets created when the script successfully finishes.
if [! -f /Scripts/file.txt]
then
: # Do nothing. Go to the next step?
else
mkdir /Scripts # file.txt will come at the end of the script
fi

# Next command (macOS preference setting)
defaults write ...

Le retour est

line 5: [!: command not found
mkdir: /Scripts: File exists

Je ne sais pas quoi faire. Chaque endroit où une recherche Google m'amène indique quelque chose de différent.

jrw
la source
6
Mettez votre code dans shellcheck.net et passez en revue les suggestions qu'il fait
roaima
12
Une raison pour laquelle vous ne pouvez pas simplement touchle fichier et sauter le conditionnel?
kirkpatt
Les autres réponses ci-dessous traitent de l'erreur de syntaxe (il manque l'espace entre [et !), mais il est probablement utile de souligner ici qu'il [s'agit d'une commande réelle sur Unix. Une commande Unix nécessite un espace entre le nom de la commande et ses arguments. Oui, c'est aussi un Bash intégré , mais il y a aussi un binaire /usr/bin/[sur la plupart des systèmes.
TheDudeAbides

Réponses:

44

Solution peut-être plus simple, pas besoin de faire des tests explicites, utilisez simplement:

mkdir -p /Scripts
touch /Scripts/file.txt

Si vous ne voulez pas que l'heure de "modification" d'un existant file.txtsoit changée touch, vous pouvez utiliser touch -a /Scripts/file.txtpour faire touchseulement changer les heures "d'accès" et "changer".

xénoïde
la source
1
Si vous ne vous souciez pas du mtime, vous pouvez l'utiliser >>/Scripts/file.txt. Cela ouvrira le fichier pour l'ajouter et le créera s'il n'existe pas.
kojiro
30

Vous obtenez l'erreur car il n'y a pas d'espace entre [et !cependant il y a aussi quelques défauts dans votre code. Vous vérifiez d'abord si le fichier n'existe pas, et sinon vous ne faites rien. Si le fichier existe, vous créez un répertoire (mais vous ne faites rien pour créer le fichier).

Vous n'avez pas non plus besoin de l'opération null, vous devriez pouvoir simplement faire:

#! /bin/bash -
if [[ ! -e /Scripts/file.txt ]]; then
    mkdir -p /Scripts
    touch /Scripts/file.txt
fi

[command2]

Ceci vérifie s'il /Scripts/file.txtn'existe pas, il créera le /Scriptsrépertoire puis le file.txtfichier. Vous pouvez également vérifier l'existence du répertoire séparément si vous le souhaitez. De plus, notez que j'utilise -eau lieu de -fcomme vous l'avez demandé simplement pour vérifier l'existence d'un fichier qui est ce -equi fera où -fvérifie qu'il s'agit d'un "fichier normal" http://tldp.org/LDP/abs/html/fto. html

Jesse_b
la source
Merci @roaima, j'ai mis à jour ma réponse avec votre suggestion.
Jesse_b
qu'est-ce que le fichier n'existe pas mais le répertoire existe?
Ant
3
@Ant: mkdir -p: crée tous les répertoires nécessaires, sans se plaindre s'il en existe déjà un. ex: mkdir / home / user1 / tmp: créera cette hiérarchie, indépendante du fait que les répertoires / home ou / home / user1 existaient auparavant. touch mettra également à jour l'heure d'un fichier existant ou en créera un nouveau si aucun fichier n'existe. On pourrait même se débarrasser de la partie if ... then, car il est tout à fait correct de simplement lancer ces 2 commandes, si vous voulez vous assurer que ces répertoires existent et que ce fichier existe à l'intérieur.
Olivier Dulac
Je vois! Merci pour la clarification :)
Ant
11

Pour commencer, le script shell n'est pas un script bash , alors rendons votre code plus général:

#!/bin/sh

Chaque système Posix doit avoir ce fichier; bash est strictement facultatif.

Pas besoin de tester si le répertoire existe, juste

dir=/Scripts
mkdir -p $dir

Pour créer le fichier s'il n'existe pas,

filename=$dir/file.txt
test -f $filename || touch $filename

Ou si vous préférez,

filename=$dir/file.txt
if [ ! -f $filename ]
then
    touch $filename
fi
James K. Lowden
la source
6

Vous avez une erreur syntaxique. Vous avez besoin d'espaces avant et après le [et ].

DopeGhoti
la source
3
#!/bin/bash

# Check for the file that gets created when the script successfully finishes.
CHECKFILE="/Scripts/file.txt"

CHECKDIR=$( dirname "$CHECKFILE" )

# The directory with the file must exist
mkdir -p "$CHECKDIR"
if [ ! -f "$CHECKFILE" ]; then
    # What to do if the file is not there
fi
touch "$CHECKFILE"

Ce qui précède suppose qu'il n'y a pas de "trucs" tels que la création d'un répertoire appelé /Scripts/file.txt(ce qui pourrait être un moyen de forcer le script à toujours entrer dans la branche if). Si le "fichier" est un répertoire, le test -f échouera et la commande tactile ne changera rien.

LSerni
la source
0

mon approche

#!/bin/sh

# input might contains spaces and other characters
FILEPATH="/tmp/some where/the file.blah"

# extract the file + dir names
FILE="`basename "${FILEPATH}"`"
DIR="`dirname "${FILEPATH}"`"

# create the dir, then the file
mkdir -p "${DIR}" && touch "${DIR}/${FILE}"

# show result
ls -l "$FILEPATH"

production

  ./dofile.sh
  -rw-r--r-- 1 jmullee jmullee 0 Nov 15 21:23 /tmp/some where/the file.blah

.

jmullee
la source
1
Vous ne vérifiez pas si le fichier existe
PiedPiper
@piepdpiper il le fait, c'est implicite dans touchetmkdir -p
xenoid
idem avec plus de contrôles ressemble à: D = / boot / bork; F = fnord; mkdir -p "$ D" && {touch "$ D / $ F" && echo "créé $ D / $ F OK"; } || {echo "n'a pas pu créer le répertoire '$ D'"; }
jmullee