Shell script per creare un file se non esiste?


20

Ho bisogno di creare uno script di shell che verifichi la presenza di un file e, se non esiste, lo crea e passa al comando successivo o passa al comando successivo. Quello che ho non lo fa.

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

Il ritorno è

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

Non ho idea di cosa fare. Ogni luogo che una ricerca di Google mi porta indica qualcosa di diverso.


6
Inserisci il tuo codice in shellcheck.net e rivedi i suggerimenti che fornisce
roaima,

12
Qualche motivo per cui non puoi semplicemente touchsalvare il file e saltare il condizionale?
Kirkpatt,

Altre risposte di seguito affrontano l'errore di sintassi (manca lo spazio tra [e !), ma è probabilmente utile sottolineare qui che [è un comando effettivo su Unix. Un comando Unix richiede uno spazio tra il nome del comando e i suoi argomenti. Sì, è anche un Bash incorporato , ma c'è anche un binario /usr/bin/[su molti sistemi.
TheDudeAbides,

Risposte:


44

Soluzione forse più semplice, non è necessario eseguire test espliciti, basta usare:

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

Se non si desidera che il tempo di "modifica" di un esistente file.txtdi essere cambiato da touch, è possibile utilizzare touch -a /Scripts/file.txtper fare touchsolo cambierà il "accesso" e tempi "cambiamento".


1
Se non ti interessa l'ora, potresti usare >>/Scripts/file.txt. Questo aprirà il file da aggiungere e lo creerà se non esiste.
Kojiro,

30

Stai ricevendo l'errore perché non c'è spazio tra [e! tuttavia ci sono anche alcuni difetti nel tuo codice. Per prima cosa stai verificando se il file non esiste e, in caso contrario, non stai facendo nulla. Se il file esiste, stai creando una directory (ma non stai facendo nulla per creare il file).

Inoltre non hai bisogno dell'operazione nulla, dovresti essere in grado di fare semplicemente:

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

[command2]

Questo sta verificando se /Scripts/file.txtnon esiste, creerà la /Scriptsdirectory e quindi il file.txtfile. Se lo desideri, puoi anche verificare l'esistenza della directory separatamente. Inoltre nota che sto usando -einvece di -fcome hai semplicemente chiesto di verificare l'esistenza di un file che è ciò -eche farà dove -fverifica che si tratti di un "file normale" http://tldp.org/LDP/abs/html/fto. html


Grazie @roaima, ho aggiornato la mia risposta con il tuo suggerimento.
Jesse_b,

qual è il file non esiste ma la directory esiste?
Formica

3
@Ant: mkdir -p: crea tutte le directory necessarie, senza lamentarti se ne esiste già una. es: mkdir / home / user1 / tmp: creerà questa gerarchia, indipendentemente dal fatto che le directory / home o / home / user1 esistessero in precedenza. touch aggiornerà anche l'ora di un file esistente o ne creerà uno nuovo se non esiste alcun file. Si potrebbe anche sbarazzarsi della parte if ... then, dato che è abbastanza giusto avviare quei 2 comandi, se si desidera assicurarsi che quelle directory esistano e che il file esista al suo interno.
Olivier Dulac,

Vedo! Grazie per il chiarimento :)
Ant

11

Per cominciare, lo script di shell non è script bash , quindi rendiamo il tuo codice più generale:

#!/bin/sh

Ogni sistema Posix deve avere quel file; bash è strettamente facoltativo.

Non c'è bisogno di testare se la directory esiste, giusto

dir=/Scripts
mkdir -p $dir

Per creare il file se non esiste,

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

O se preferisci,

filename=$dir/file.txt
if [ ! -f $filename ]
then
    touch $filename
fi

6

Hai un errore sintattico. Sono necessari spazi prima e dopo il [e ].


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"

Quanto sopra presuppone che non ci siano "trucchi" come la creazione di una directory chiamata /Scripts/file.txt(che potrebbe essere un modo per forzare lo script a inserire sempre il ramo if). Se il "file" è una directory, il test -f fallirà e il comando touch non cambierà nulla.


0

il mio approccio

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

produzione

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

.


1
Non stai verificando se il file esiste
PiedPiper

@piepdpiper lo fa, questo è impliciit in touchemkdir -p
xenoid

gli stessi id con più controlli sono: D = / boot / bork; F = fnord; mkdir -p "$ D" && {tocca "$ D / $ F" && echo "ha creato $ D / $ F OK"; } || {echo "impossibile creare dir '$ D'"; }
jmullee,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.