So entfernen Sie die Dateinamenerweiterung aus einer Liste von Dateinamen in bash

Ich versuche, die Dateinamenerweiterung aus einer Liste von Dateien zu entfernen, die ich wie folgt generiert habe Bash-Skript:

 #!/bin/bash file_list=$(find . -type f) #assuming that the files are stored in the same directory trimmed_file_list=$(printf "%s\n" "${file_list[@]%.*}") printf "%s\n" "${trimmed_file_list[@]}" 

Diese Erweiterung schneidet die Erweiterung vom letzten Eintrag in der Liste ab, jedoch nicht von einem der früheren.

Zum Beispiel möchte ich die folgende Liste:

 file1.pdf file2.pdf file3.png 

 file1 file2 file3 

Aber stattdessen bekomme ich:

 file1.pdf file2.pdf file3 

Ich würde es vorziehen, dies nicht in einer Schleife zu tun, ich würde gerne die Parametererweiterung verwenden. Ich möchte Kürzungen vermeiden, da ich immer nur die letzte Erweiterung in der Datei entfernen möchte.

Es gibt eine ganze Reihe von Themen zur Parametererweiterung, und es scheint, dass bash an “ verwendet Zeilenumbrüche … Ich bin mir wirklich nicht sicher. Wenn ein anderes der bereits vorhandenen Themen dieses Problem erklärt, verstehe ich nicht ganz, was los ist.

Themen, die scheinen verwandt, aber scheint mein Problem nicht zu lösen:

Kommentare

  • Ihr Titel erwähnt Arrays, aber Ihr Code enthält kein Array.
  • @Kusalananda Danke! Ich ‚ habe das erkannt, seit ich gefragt habe. Ich lerne noch 🙂
  • @Kusalananda Ich ‚ habe die Frage geändert, um sie besser an das Problem anzupassen. Dies sollte verhindern, dass fehlerhafte Google-Suchanfragen auf die Seite gelangen. Vielen Dank für die Informationen!

Antwort

Sie können alles in einem Befehl ausführen.

find /path/to -type f -execdir bash -c "printf "%s\n" "${@%.*}"" bash {} + 

Kommentare

  • Danke! Ich muss tatsächlich ein paar Kopien des Arrays erstellen, eine für ein Menü, dessen Dateiname geändert wurde, und eine, die den ursprünglichen Indexwert beibehält, damit ich die Datei über das Menü aufrufen kann. Es ist wirklich erstaunlich, wie viel Bash tun kann! Die Fähigkeit, alles in einen Befehl einzubetten, haut mich immer noch um! : D

Antwort

Ich glaube, Sie möchten ein Array anstelle einer Zeichenfolge erstellen:

IFS=$"\n" # split on newline only set -o noglob # disable the glob part file_list=($(find . -name "*.*" -type f)) 

Oder mit Bash 4.4+, ohne auf Dateipfaden mit Zeilenumbrüchen zu brechen:

readarray -td "" file_list < <(find . -name "*.*" -type f -print0) 

Dann sollte Ihre Parametererweiterung funktionieren, obwohl es hier sinnvoller wäre, wieder eine Array-Variable zu verwenden:

trimmed_file_list=("${file_list[@]%.*}") 

In Ihrem Codebeispiel erstellen Sie eine Zeichenfolge Bitten Sie dann die Parametererweiterung, alles nach dem letzten Punktzeichen in der vollständigen Zeichenfolge zu entfernen.

Kommentare

  • Vielen Dank! Ich werde es testen, sobald ich morgens auf meinem Schreibtisch bin.
  • Dies setzt voraus, dass keine Dateinamen in diesem Verzeichnis Leerzeichen oder Globbing-Zeichen enthalten.
  • @Wildcard sollte sein adressiert von der letzten Bearbeitung.
  • @Wildcard Danke für den Zeiger! Ich ‚ generiere die Dateien, die programmgesteuert in dieses Verzeichnis verschoben werden, damit ‚ kein Problem darstellt.

Antwort

Ihr Code enthält keine Arrays. Außerdem wird eine Liste von Dateinamen in eine Zeichenfolge $file_list eingefügt. Der Inhalt der Zeichenfolge endet mit file3.png, und Ihre Parametersubstitution entfernt .png aus der Zeichenfolge, sodass Sie eine einzelne Zeichenfolge mit Dateinamen erhalten Der letzte Dateiname hat kein Dateinamensuffix.

Durch das Einfügen mehrerer separater Objekte (Pfadnamen) in eine einzelne Zeichenfolge wird das Skript automatisch von der ordnungsgemäßen Funktion für Dateien ausgeschlossen, deren Namen Leerzeichen enthalten (oder welches Trennzeichen die Zeichenfolge verwendet). Die Verwendung eines Arrays würde nicht helfen, da Sie die Ausgabe von find auf Leerzeichen aufteilen würden.


Zum Trimmen der Erweiterung aller Dateinamen regulärer Dateien im oder unter dem aktuellen Verzeichnis:

find . -type f -name "*.*" -exec sh -c " for pathname do printf "Would move %s to %s...\n" "$pathname" "${pathname%.*}" # mv -i "$pathname" "${pathname%.*}" done" sh {} + 

Hier wird nach regulären Dateien gesucht, deren Namen mindestens einen Punkt enthalten. Die Pfadnamen dieser Dateien werden stapelweise in ein kleines Shell-Skript eingegeben, das sie durchläuft. Das Shell-Skript benennt die Dateien um, indem der letzte Punkt im Dateinamen und alles, was danach kommt, entfernt wird. Der tatsächliche Befehl mv ist aus Sicherheitsgründen auskommentiert.

Der Befehl find fungiert als Generator für Pfadnamen für internes Shell-Skript, und wir werden garantiert Pfadnamen, die Leerzeichen, Zeilenumbrüche und Tabulatoren enthalten, ordnungsgemäß verarbeiten. Die Ausgabe von Befehlen muss nicht in Variablen gespeichert werden.

Wenn Sie ein Array von Pfadnamen haben, die möglicherweise mit

shopt -s globstar nullglob file_list=( **/*.* ) # get pathnames of files with dots in their names 

erstellt wurden, können Sie die Pfadnamen ohne Suffixe mit ausgeben

printf "%s\n" "${file_list[@]%.*}" 

Ob dies Ihnen helfen würde, weiß ich nicht. Wenn Sie die Pfadnamen ohne Suffixe für etwas verwenden möchten Wenn Sie dann die Ausgabe des obigen Befehls printf verwenden, ist dies falsch (Sie können wieder keinen seltsamen Pfadnamen mehr verarbeiten) und wie Sie die Dateinamensuffixe löschen, hängt davon ab, was Sie mit dem Ergebnis machen möchten.

Verwandte Themen:

Kommentare

  • Danke! Ihre Beherrschung der Bash ist sehr offensichtlich! Ich ‚ kratzt immer noch an der Oberfläche … Vielen Dank, dass Sie sich die Zeit genommen haben, um zu helfen 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.