GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Erstellen Sie eine neue Datei, aber fügen Sie eine Nummer hinzu, wenn der Dateiname bereits in der Bash vorhanden ist

Um die Rennbedingungen zu vermeiden :

name=some-file

n=
set -o noclobber
until
  file=$name${n:+-$n}.ext
  { command exec 3> "$file"; } 2> /dev/null
do
  ((n++))
done
printf 'File is "%s"\n' "$file"
echo some text in it >&3

Und zusätzlich haben Sie die Datei zum Schreiben auf fd 3 geöffnet.

Mit bash-4.4+ , können Sie daraus eine Funktion machen wie:

create() { # fd base [suffix [max]]]
  local fd="$1" base="$2" suffix="${3-}" max="${4-}"
  local n= file
  local - # ash-style local scoping of options in 4.4+
  set -o noclobber
  REPLY=
  until
    file=$base${n:+-$n}$suffix
    eval 'command exec '"$fd"'> "$file"' 2> /dev/null
  do
    ((n++))
    ((max > 0 && n > max)) && return 1
  done
  REPLY=$file
}

Zum Beispiel zu verwenden als:

create 3 somefile .ext || exit
printf 'File: "%s"\n' "$REPLY"
echo something >&3
exec 3>&- # close the file

Die max Wert kann zum Schutz vor Endlosschleifen verwendet werden, wenn die Dateien aus anderen Gründen als noclobber nicht erstellt werden können .

Beachten Sie, dass noclobber gilt nur für > Operator, nicht >> noch <> .

Verbleibende Rennbedingung

Eigentlich noclobber entfernt die Racebedingung nicht in allen Fällen. Es verhindert nur das regelmäßige Klobben Dateien (keine anderen Dateitypen, sodass cmd > /dev/null schlägt beispielsweise nicht fehl) und hat in den meisten Shells selbst eine Race-Bedingung.

Die Shell macht zuerst einen stat(2) auf die Datei, um zu prüfen, ob es sich um eine reguläre Datei handelt oder nicht (fifo, Verzeichnis, Gerät ...). Nur wenn die Datei (noch) nicht existiert oder eine normale Datei ist, wird 3> "$file" ausgeführt Verwenden Sie das O_EXCL-Flag, um sicherzustellen, dass die Datei nicht geclobbt wird.

Wenn es also eine Fifo- oder Gerätedatei mit diesem Namen gibt, wird sie verwendet (vorausgesetzt, sie kann nur im Schreibmodus geöffnet werden), und eine normale Datei kann geclobbered werden, wenn sie als Ersatz für ein Fifo/Gerät/Verzeichnis erstellt wird. .. dazwischen stat(2) und open(2) ohne O_EXCL!

Ändern der

  { command exec 3> "$file"; } 2> /dev/null

zu

  [ ! -e "$file" ] && { command exec 3> "$file"; } 2> /dev/null

Würde die Verwendung einer bereits vorhandenen nicht regulären Datei vermeiden, aber die Race-Bedingung nicht ansprechen.

Nun, das ist nur angesichts eines böswilligen Angreifers wirklich ein Problem, das Sie dazu bringen möchte, eine beliebige Datei im Dateisystem zu überschreiben. Es entfernt die Racebedingung im Normalfall, wenn zwei Instanzen desselben Skripts gleichzeitig ausgeführt werden. Insofern also besser als Ansätze, die vorher nur mit [ -e "$file" ] auf Dateiexistenz prüfen .

Für eine funktionierende Version ohne Race Condition könnten Sie den zsh verwenden Shell anstelle von bash die eine rohe Schnittstelle zu open() hat als sysopen eingebaut in zsh/system Modul:

zmodload zsh/system

name=some-file

n=
until
  file=$name${n:+-$n}.ext
  sysopen -w -o excl -u 3 -- "$file" 2> /dev/null
do
  ((n++))
done
printf 'File is "%s"\n' "$file"
echo some text in it >&3

Einfacher:

touch file`ls file* | wc -l`.ext

Sie erhalten:

$ ls file*
file0.ext  file1.ext  file2.ext  file3.ext  file4.ext  file5.ext  file6.ext

Das folgende Skript kann Ihnen dabei helfen. Sie sollten nicht mehrere Kopien des Skripts gleichzeitig ausführen, um eine Race-Condition zu vermeiden.

name=somefile
if [[ -e $name.ext || -L $name.ext ]] ; then
    i=0
    while [[ -e $name-$i.ext || -L $name-$i.ext ]] ; do
        let i++
    done
    name=$name-$i
fi
touch -- "$name".ext

Linux
  1. Wie füge ich in Bash nach jeder Zeile in einer Datei eine Zeichenfolge hinzu?

  2. So schließen Sie eine Datei in ein Bash-Shell-Skript ein

  3. So fügen Sie der Bash-Eingabeaufforderung ein Symbol hinzu

  4. atomare Erstellungsdatei, falls nicht aus dem Bash-Skript vorhanden

  5. Wie man nur die Anzahl der Zeilen einer Datei erhält

So erstellen Sie ein neues Ext4-Dateisystem (Partition) unter Linux

So überprüfen Sie, ob eine Datei oder ein Verzeichnis in Bash vorhanden ist

4 Möglichkeiten zum Erstellen einer neuen Datei unter Linux

So fügen Sie unter Linux ein neues Gerät zum BTRFS-Dateisystem hinzu

Nautilus-Kontextmenüoption zum Erstellen einer neuen Datei?

So überprüfen Sie, ob eine Datei oder ein Verzeichnis in der Bash-Shell vorhanden ist