Shell-Skript zum Erstellen einer Datei, wenn es nicht existiert?

19

Ich muss ein Shell-Skript erstellen, das auf das Vorhandensein einer Datei prüft. Wenn es nicht vorhanden ist, wird die Datei erstellt und der nächste Befehl oder nur der nächste Befehl ausgeführt. Was ich habe, macht das nicht.

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

Rückkehr ist

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

Keine Ahnung was zu tun ist. Jeder Ort, den ich bei einer Google-Suche finde, weist auf etwas anderes hin.

jrw
quelle
6
Gib deinen Code in shellcheck.net ein und überprüfe die Vorschläge
roaima 15.11.17
12
Kannst du nicht einfach touchdie Datei und die Bedingung überspringen?
Kirkpatt
Andere Antworten behandeln den Syntaxfehler (ohne Leerzeichen zwischen [und !), aber es ist wahrscheinlich hilfreich, hier darauf hinzuweisen, dass [es sich um einen tatsächlichen Befehl unter Unix handelt. Ein Unix-Befehl erfordert ein Leerzeichen zwischen dem Befehlsnamen und seinen Argumenten. Ja, es ist auch eine Bash- Version , aber /usr/bin/[auf den meisten Systemen gibt es auch eine Binärdatei .
TheDudeAbides

Antworten:

43

Möglicherweise einfachere Lösung, keine expliziten Tests erforderlich, verwenden Sie einfach:

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

Wenn Sie die „Änderung“ Zeit eines nicht wollen bestehende file.txtdurch geändert werden touch, können Sie verwenden , touch -a /Scripts/file.txtum touchnur den „Zugang“ zu ändern und „change“ Zeiten.

Magnet
quelle
1
Wenn Sie sich nicht für die Zeit interessieren, könnten Sie verwenden >>/Scripts/file.txt. Dadurch wird die Datei zum Anhängen geöffnet und erstellt, falls sie nicht vorhanden ist.
Kojiro
29

Sie erhalten den Fehler, weil kein Leerzeichen dazwischen steht [und !es auch einige Fehler in Ihrem Code gibt. Zuerst prüfen Sie, ob die Datei nicht vorhanden ist, und wenn nicht, tun Sie nichts. Wenn die Datei vorhanden ist, erstellen Sie ein Verzeichnis (tun jedoch nichts, um die Datei zu erstellen).

Sie brauchen auch nicht die Null-Operation, Sie sollten in der Lage sein, einfach zu tun:

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

[command2]

Wenn /Scripts/file.txtdies nicht der Fall ist, wird zuerst das /ScriptsVerzeichnis und dann die file.txtDatei erstellt. Sie können das Vorhandensein des Verzeichnisses auch separat prüfen, wenn Sie dies wünschen. Außerdem bemerke ich bin mit -estatt , -fwie Sie einfach für die Existenz einer Datei zu überprüfen gefragt , die was -ewo tut -füberprüft, ob es sich um eine „reguläre Datei“ http://tldp.org/LDP/abs/html/fto. html

Jesse_b
quelle
Danke @roaima, ich habe meine Antwort mit Ihrem Vorschlag aktualisiert.
Jesse_b
Was ist die Datei nicht existiert, aber das Verzeichnis?
Ant
3
@Ant: mkdir -p: Erstellt alle erforderlichen Verzeichnisse, ohne sich zu beschweren, ob eines bereits vorhanden ist. Beispiel: mkdir / home / user1 / tmp: erstellt diese Hierarchie, unabhängig davon, ob die Verzeichnisse / home oder / home / user1 zuvor vorhanden waren. touch aktualisiert auch nur die Uhrzeit einer vorhandenen Datei oder erstellt eine neue, wenn keine Datei vorhanden ist. Man könnte sogar den Teil if ... then loswerden, da es in Ordnung ist, nur diese beiden Befehle zu starten, wenn Sie sicherstellen möchten, dass diese Verzeichnisse und diese Datei darin vorhanden sind.
Olivier Dulac
Aha! Vielen Dank für die Klarstellung :)
Ant
11

Zunächst ist das Shell-Skript kein Bash-Skript . Machen wir den Code also allgemeiner:

#!/bin/sh

Jedes Posix-System muss diese Datei haben. Bash ist streng optional.

Es ist nicht nötig zu testen, ob das Verzeichnis existiert

dir=/Scripts
mkdir -p $dir

So erstellen Sie die Datei, wenn sie nicht vorhanden ist:

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

Oder wenn Sie es vorziehen,

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

Sie haben einen syntaktischen Fehler. Sie benötigen Leerzeichen vor und nach dem [und ].

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

Das oben Gesagte geht davon aus, dass es keine "Tricks" wie das Erstellen eines eines Verzeichnisses genannt /Scripts/file.txt(das könnte ein Weg , um das Skript sein, immer zu zwingen , die , wenn Zweig eingeben). Wenn die "Datei" ein Verzeichnis ist, schlägt der -f-Test fehl und der Touch-Befehl ändert nichts.

LSerni
quelle
0

mein Ansatz

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

Ausgabe

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

.

jmullee
quelle
1
Sie überprüfen nicht, ob die Datei vorhanden ist
PiedPiper
@piepdpiper tut er, dies ist implizit in touchundmkdir -p
Xenoid
Die gleichen IDs mit mehr Überprüfungen sehen so aus: D = / boot / bork; F = fnord; mkdir -p "$ D" && {touch "$ D / $ F" && echo "created $ D / $ F OK"; } || {echo "Verzeichnis '$ D' konnte nicht erstellt werden"; }
jmullee