Wie kann ich ein Zitat im Bash-Skript ersetzen?

488
Walter Schrabmair

Ich habe dieses Bash-Skript

 #!/bin/bash find . -type f > /home/wschrabi/filenames while read filename; do stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][!\"\#\$\%\&\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_`{|}~]')"; ohne="$(sed -e 's/[\d126-\d255\"*:<>\?\\\|]/_/g' <<<$filename)"; test "$filename" = "$stripped" || printf "mv '%s' '%s'\n " "$" "$";  done < /home/wschrabi/filenames 

und an der Stelle $möchte ich ein einfaches Anführungszeichen im Dateinamen verwenden. Der Zweck sollte sein, dass ich, wenn ich die Ausgabe in einem Bash-Skript pfeife, alle Dateinamen automatisch umbenennen möchte. Aber die einfachen Anführungszeichen machen Probleme.

Vielen Dank für alle Ratschläge. Walter

BEARBEITEN: Hier ist mein chekc NTFS-Skript für Dateinamen.

 #!/bin/bash # # Quote a string, wrapping it in tick marks ('), and escaping any # embedded ticks. # # Inputs: # $1: The string to quote # # Returns: # (stdout) - The quoted string # quote() { if [ $(echo "$@" | tr -d "\n" | wc -c) -eq 0 ]; then echo "''" elif [ $(echo "$@" | tr -d "[a-z][A-Z][0-9]:,.=~_/\n-" | wc -c) -gt 0 ]; then echo "$@" | sed -e "s/'/\'\"\'\"\'/g" | sed -e "s/^/'/g" -e "s/$/'/g" else echo "$@" fi }  if [ $# -eq 0 ] then echo "No arguments supplied: USAGE: checkNTFS_filenames.sh <file_to_check>"  fi  if [ $# -eq 1 ] then  #find . -type f > /home/wschrabi/filenames2 while read filename; do stripped="$(printf '%s\n' "$filename" | tr -d '\"\*\:\<\>\?\\\|')"; ohne="$(sed -e 's/[\d126-\d255\"*:<>\?\\\|]/_/g' <<<$filename)"; if [ "$filename" != "$stripped" ] ; then printf "mv %s %s\n" "$(quote "$filename")" "$(quote "$stripped")"  fi done < $1 fi 
2
Ich habe eine weitere Antwort hinzugefügt, um nicht von virtex abzulenken, was richtig ist, sondern um auf kürzere, effizientere Wege hinzuweisen, dies zu tun. MariusMatutiae vor 7 Jahren 0

2 Antworten auf die Frage

0
virtex

Wenn Sie Ihre Dateinamen zwischen Häkchen setzen, funktioniert das Umgehen von Zeichen mit einem Backslash nicht. Es gibt jedoch eine andere Möglichkeit, dies zu tun. Hier ist eine Zitat-Funktion, die ich in der Vergangenheit verwendet habe und die für Sie nützlich sein könnte.

# # Quote a string, wrapping it in tick marks ('), and escaping any # embedded ticks. # # Inputs: # $1: The string to quote # # Returns: # (stdout) - The quoted string # quote() { if [ $(echo "$@" | tr -d "\n" | wc -c) -eq 0 ]; then echo "''" elif [ $(echo "$@" | tr -d "[a-z][A-Z][0-9]:,.=~_/\n-" | wc -c) -gt 0 ]; then echo "$@" | sed -e "s/'/\'\"\'\"\'/g" | sed -e "s/^/'/g" -e "s/$/'/g" else echo "$@" fi } 

Wenn Sie es ausführen, erhalten Sie solche Ausgaben.

$ quote abc abc $ quote "abc'def" 'abc'"'"'def' $ quote \"abc\" '"abc"' $ quote "abc def" 'abc def' 

Die Idee hier ist, dass Sie die letzte printf in Ihrem Skript folgendermaßen ersetzen können:

printf "mv %s %s\n" "$(quote "$filename")" "$(quote "$ohne")" 

Mit einem Dateinamen von abc'def in Ihrem Skript mit der obigen Änderung habe ich dies als meine Ausgabe erhalten.

mv 'abc'"'"'def' abcdef 

und die Datei wurde bei der Ausführung erfolgreich umbenannt.

Danke für ein Protokoll Walter Schrabmair vor 7 Jahren 0
0
MariusMatutiae

Die Antwort von Virtex ist natürlich vollkommen richtig. Ich möchte nur darauf hinweisen, dass diese Art der Bedienung einfacher ist, mit zur Durchführung von Bash - Arrays : nur deutlich zu machen, nehmen wir an, wir die ersten Zeichen abzustreifen wollen ./, die finden Blätter auf den Dateinamen in dieser einfachen Befehl :

find -maxdepth 1 -type f 

Dies kann wie folgt durchgeführt werden:

#!/bin/bash  declare -a mylist mylist=(`find -maxdepth 1 -type f `) mylist=($) echo "$" 

Bash-Suchen und Ersetzen funktioniert auf Arrays, wie man hoffen würde: indem Sie die Array-Elemente nacheinander ändern. Dies kann geändert werden, um Ihr Beispiel einzuschließen.

BEARBEITEN :

Was ist, wenn ich Millionen von Dateien habe?

Wie wäre es mit 10 Millionen?

$ time /bin/bash -c 'unset array && declare -a array && array=($(seq 1 10000000)) && echo "$"; unset array' 7  real 0m11.110s user 0m10.412s sys 0m0.724s  $ inxi -C CPU: Dual core Intel Core i7-5500U (-HT-MCP-) cache: 4096 KB  clock speeds: max: 3000 MHz 1: 2509 MHz 2: 2471 MHz 3: 2631 MHz 4: 2471 MHz 
Danke Marius, aber was ist, wenn ich Millionen von Dateien habe? Gibt es ein RAM-Speicherlimit für die Bash-Arrays? Walter Schrabmair vor 7 Jahren 0
@WalterSchrabmair Pls siehe meine Bearbeitung. MariusMatutiae vor 7 Jahren 0