¿Script de Shell para crear un archivo si no existe?

19

Necesito crear un script de shell que verifique la presencia de un archivo y, si no existe, lo crea y pasa al siguiente comando, o simplemente pasa al siguiente comando. Lo que tengo no hace eso.

#!/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 ...

El retorno es

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

Ni idea de qué hacer. Cada lugar que me trae una búsqueda de Google indica algo diferente.

jrw
fuente
66
Ponga su código en shellcheck.net y revise las sugerencias que hace
roaima
12
¿Alguna razón por la que no puede simplemente touchel archivo y omitir el condicional?
kirkpatt
Otras respuestas a continuación abordan el error de sintaxis (falta el espacio entre [y !), pero probablemente sea útil señalar aquí que [es un comando real en Unix. Un comando Unix requiere un espacio en blanco entre el nombre del comando y sus argumentos. Sí, también es un Bash incorporado , pero también hay un binario en la /usr/bin/[mayoría de los sistemas.
TheDudeAbides

Respuestas:

43

Posiblemente una solución más simple, no es necesario hacer pruebas explícitas, solo use:

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

Si no desea que el tiempo de "modificación" de una ya existente file.txtque ser cambiado por touch, se puede utilizar touch -a /Scripts/file.txtpara hacer touchsolamente cambiar el "acceso" y "tiempos de cambio".

xenoide
fuente
1
Si no te importa el mtime, puedes usarlo >>/Scripts/file.txt. Esto abrirá el archivo para agregarlo y crearlo si no existe.
kojiro
29

Obtiene el error porque no hay espacio entre ellos [y, !sin embargo, también hay algunos defectos en su código. Primero está verificando si el archivo no existe, y si no está haciendo nada. Si el archivo sí existe, está creando un directorio (pero no está haciendo nada para crear el archivo).

Tampoco necesita la operación nula, simplemente debería poder hacer:

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

[command2]

Esto está comprobando si /Scripts/file.txtno existe, creará el /Scriptsdirectorio y luego el file.txtarchivo. También puede verificar la existencia del directorio por separado si lo desea. Además, observe que estoy usando en -elugar de lo -fque me pidió, simplemente para verificar la existencia de un archivo, que es lo -eque hará cuando -fverifique que es un "archivo normal" http://tldp.org/LDP/abs/html/fto. html

Jesse_b
fuente
Gracias @roaima, he actualizado mi respuesta con tu sugerencia.
Jesse_b
¿Cuál es el archivo no existe pero el directorio sí?
Ant
3
@Ant: mkdir -p: crea todos los directorios necesarios, sin quejarse si ya existe uno. Por ejemplo: mkdir / home / user1 / tmp: creará esta jerarquía, independientemente del hecho de que los directorios / home o / home / user1 existieran de antemano. touch también solo actualizará la hora de un archivo existente o creará uno nuevo si no existía ningún archivo. Incluso podría deshacerse de la parte if ... then, ya que está bien iniciar esos 2 comandos, si desea asegurarse de que esos directorios existan y que el archivo exista dentro de ellos.
Olivier Dulac
¡Veo! Gracias por la aclaración :)
Ant
11

Para empezar, el script de shell no es bash script , así que hagamos que su código sea más general:

#!/bin/sh

Todos los sistemas Posix deben tener ese archivo; bash es estrictamente opcional.

No es necesario probar si el directorio existe, solo

dir=/Scripts
mkdir -p $dir

Para crear el archivo si no existe,

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

O si lo prefieres

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

Tienes un error sintáctico. Necesita espacios antes y después de [y ].

DopeGhoti
fuente
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"

Lo anterior supone que no hay "trucos", como crear un directorio llamado /Scripts/file.txt(que podría ser una forma de obligar al script a ingresar siempre la rama if). Si el "archivo" es un directorio, la prueba -f fallará y el comando táctil no cambiará nada.

LSerni
fuente
0

mi acercamiento

#!/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"

salida

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

.

jmullee
fuente
1
No está comprobando si el archivo existe
PiedPiper
@piepdpiper lo hace, esto es impliciit en touchemkdir -p
xenoid
Las mismas ideas con más comprobaciones se ven así: D = / boot / bork; F = fnord; mkdir -p "$ D" && {touch "$ D / $ F" && echo "creó $ D / $ F OK"; } || {echo "no pudo crear dir '$ D'"; }
jmullee