Shell скрипт для створення файлу, якщо його не існує?


20

Мені потрібно створити скрипт оболонки, який перевіряє наявність файлу, а якщо його не існує, створює його і переходить до наступної команди або просто переходить до наступної команди. Те, що я маю, не робить цього.

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

Повернення є

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

Поняття не маю, що робити. Кожне місце, де мені приходить пошук Google, вказує на щось інше.


6
Введіть свій код на shellcheck.net та перегляньте його пропозиції
roaima

12
З будь-якої причини ви не можете просто touchфайл та пропустити умовне?
kirkpatt

Інші відповіді нижче стосуються помилки синтаксису (пропущений пробіл між [і !), але, мабуть, корисно вказати тут, що [це фактична команда для Unix. Команда Unix вимагає деякого пробілу між назвою команди та її аргументами. Так, це також Bash вбудований , але в /usr/bin/[більшості систем також є двійковий код.
TheDudeAbides

Відповіді:


44

Можливо, простіше рішення, не потрібно робити явні тести, просто використовуйте:

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

Якщо ви не хочете «модифікації» час існуючого file.txtбути змінений touch, ви можете використовувати , touch -a /Scripts/file.txtщоб touchзмінити тільки «доступ» і «зміна» раз.


1
Якщо вас не хвилює mtime, ви можете використати >>/Scripts/file.txt. Це відкриє файл для додавання та створить його, якщо його не існує.
kojiro

30

Ви отримуєте повідомлення про помилку , тому що немає ніякого простору між [і !тим НЕ менш є і деякі недоліки в вашому коді. Спочатку ви перевіряєте, чи файл не існує, а якщо ні, ви нічого не робите. Якщо файл існує, ви створюєте каталог (але нічого не робите, щоб створити файл).

Вам також не потрібна нульова операція, ви повинні мати можливість просто робити:

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

[command2]

Це перевірка, чи /Scripts/file.txtне існує, створить /Scriptsкаталог, а потім file.txtфайл. Ви також можете перевірити наявність каталогу, якщо хочете. Додатково зауважте, що я використовую -eзамість того, -fяк ви попросили просто перевірити наявність файлу, і що -eробити, коли -fперевіряється, що це "звичайний файл" http://tldp.org/LDP/abs/html/fto. html


Дякую @roaima, я оновив свою відповідь на вашу пропозицію.
Jesse_b

що файлу не існує, але це каталог?
Мураш

3
@Ant: mkdir -p: створити всі необхідні каталоги, не поскаржившись, якщо такий вже існує. Наприклад: mkdir / home / user1 / tmp: створить цю ієрархію, незалежну від факту, що раніше існували каталоги / home, або / home / user1. touch також просто оновить час існуючого файлу або створить новий, якщо жодного файлу не існувало. Можна навіть позбутися від частини if, то тоді, оскільки цілком нормально запустити ці 2 команди, якщо ви хочете переконатися, що ці каталоги існують і цей файл існує в ньому.
Олів'є Дулак

Я бачу! Дякую за роз’яснення :)
Ant Ant

11

Для початку скрипт оболонки не є скриптом bash , тому давайте зробимо ваш код більш загальним:

#!/bin/sh

Кожна система Posix повинна мати цей файл; Баш суворо необов'язковий.

Немає необхідності перевіряти, чи існує каталог, просто

dir=/Scripts
mkdir -p $dir

Щоб створити файл, якщо його не існує,

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

Або якщо ви віддаєте перевагу,

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

6

У вас синтаксична помилка. Вам потрібні пробіли до і після [та ].


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"

Вищесказане передбачає, що немає жодних "хитрощів", ​​таких як створення каталогу, який називається /Scripts/file.txt(що може бути способом змусити скрипт завжди входити до гілки if). Якщо "файл" - це каталог, тест -f не вдасться, а команда touch нічого не змінить.


0

мій підхід

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

вихід

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

.


1
Ви не перевіряєте, чи існує файл
PiedPiper

@piepdpiper він це робить, це вразливо touchі вmkdir -p
ксеноїд

такі ж ідентичні елементи з більшою кількістю перевірок виглядають так: D = / boot / bork; F = fnord; mkdir -p "$ D" && {touch "$ D / $ F" && echo "створив $ D / $ F ОК"; } || {echo "не вдалося створити dir '$ D'"; }
jmullee
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.