• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Wechselnde Pfade in einer Datei ersetzen: Geht das? Wie

Saber_Rider schrieb:
torrent_hash20:ÛÍÔ*î¥xŒG
wird zu
torrent_hash20:ÛÍÔ*î¥x G
Hallo Saber_Rider,
hab leider bisher keine Zeit gehabt. Das Wegfallen des Zeichens findet bei mir in der Konsole nicht statt. Mit "cat download.config" siehst du es, und (nach Ausführen meines Skripts) "cat Download.config.tmp" ist es weg? Vielleicht ein Schriftarten-/Kodierungsproblem? Ich benutze Efont Fixed für Konsole, und als Standardkodierung ISO-8859-15. Kannst du das noch mal mit 'nem Hexeditor überprüfen?
Bei mir findet sich in beiden Dateien der Code "bc" für das Zeichen.
In der Realität wird dieses File sich natürlich ändern, und ich hatte gehofft, dann einfach ein Skript drüberlaufen zu lassen, das schaut was für Downloads drin stehen, bei denen die Pfade anpasst, und das als Windows-Config speichert.
Genau das sollte mein Skript tun...
 
Ich habe auch vermutet, dass da ein Zeichensatz-Problem reinspielt, aber ich werd alles noch mal prüfen. Komischerweise ging jetzt das neue Skript von notoxp ohne die Zeichen zu löschen .

Fragen über Fragen.

Ich danke euch beiden auf jeden Fall ganz herzlich, ich werd jetzt wohl mal beide Lösungen intensiv probieren. Und wenn alles klappt versuch ich zu verstehen was zum Henker ihr da macht ;-)
 
Schieb mir doch die Datei mal per email rüber, dann sind wenigstens Zeichensatz-Ratespiele unnötig. Mailadresse kommt per PN.
 
@notoxp:

Wie müsste ich denn das Skript ändern, um den umgekehrten Weg zu gehen, also von D:\... zu /45gb_speicher...? Alles was ich bisher versucht hab ging nicht.

Code:
#!/usr/bin/perl

use strict;

my   $suche='D:\Downloads\Azureus_Torrents';
my $ersetze='/45gb_speicher/Downloads/Azureus_Torrents';


undef $/;      # gesamte Datei auf einmal lesen
$_=<STDIN>;    # von Standardeingabe lesen

my $length_diff=length($ersetze) - length($suche);  # Längendifferenz

# Ersetzen
s/(\d+):$suche([^:]*)/$1+$length_diff . ":$ersetze" . &slash($2)/eg;

print;         # gesamte Datei auf einmal ausgeben

sub slash {       # konvertiere BACKslash zu slash
    my $dir=$_[0];
  $dir=~tr#\\#\/#;
    return $dir;
}

Geändert hab ich die ersetzen/suchen Pfade sowie die Zeile mit der Backslash/Slash Ersetzung.
 
Hallo Saber_Rider,
probier doch dies mal aus:
Code:
#!/bin/bash

# User Prefs
linpath="/Daten/"
winpath="X:\\" # Doppelter Backslash!
#set -x    # Debugging

linp_l=${#linpath} # Länge
winp_l=${#winpath}
path_diff_l=$[linp_l-winp_l] # Diff der Längen

if [ -r "$1" ] # Datei vorhanden?
then	config="`cat \"$1\"`" # dann einlesen
else	echo "Bitte (lesbare) zu konvertierende Datei angeben: \"$0 datei.config\""
	exit 1
fi
while expr "$config" : '.*:' > /dev/null # wiederholen, solange noch Abschnitte übrig sind
do	key="${config%%:*}" # Abschnitt einlesen...
	config="${config#*:}" # ...und löschen
	if l=`expr "$key" : 'save_dir\([[:digit:]]\+\)'` # wenn Abschnitt="save_dirZZ", l=ZZ
	then	# String für sed präparieren
		sedstr="${sedstr}
		s/${key}/save_dir$[l-path_diff_l]/g"
		continue
	fi
	if l=`expr "$key" : 'path\([[:digit:]]\+\)'` # wenn Abschnitt="pathZZ", l=ZZ
	then	sedstr="${sedstr}
		s/${key}/path$[l-path_diff_l]/g"
		continue
	fi
	if l=`expr "$key" : 'torrent\([[:digit:]]\+\)'`
	then	sedstr="${sedstr}
		s/${key}/torrent$[l-path_diff_l]/g"
		continue
	fi
	if expr "$key" : "$linpath" > /dev/null # Pfadersetzung nötig?
	then	keynew=`echo "$key" | sed -e "s@${linpath}@${winpath}\\\\\\\\\@; s@/@\\\\\\\\\\\\\@g"` # Mehrere Quotinglevels sind doof.
		sedstr="${sedstr}
		s@${key}@${keynew}@g"
	fi
done
sedstr=`echo "$sedstr"|sort|uniq` # Mehrfachersetzungen(!) und unnütze Arbeit vermeiden
sed -e "$sedstr" "$1" > "$1".win # Alles in einem Durchgang ersetzen und als "${eingabedatei}.win" speichern
Ersetzt /Daten/ durch X:\ (in den ersten Zeilen festlegbar), / durch \ und passt die Längen an, läßt alles andere aber unberührt (auch Null-Strings und so'n Zeugs in Hashes). Dauert jetzt aber etwas länger als die letzte Version.

Aufruf: ./skriptname configdatei
Ergebnis in: configdatei.win
 
@SoeDib:
Sieht gut aus beim Überfliegen der erhaltenen Datei. Werd das nachher mal unter Windows testen.

Ach ja, bevor ich es vergesse: Danke an notoxp und dich. Ganz herzlichen Dank. Und allen anderen natürlich auch.
 
Also: Sowohl die Lösung von Soedib als auch die von notoxp erzeugen dieselbe, identische Datei (mit den bei mir geänderten Pfadangaben). Das ist doch mal gut gemacht. Und sie funktioniert unter Windows auch.

Jetzt muss ich nur noch den anderen Weg finden, von Windows nach Linux umzuwandeln.
 
SoeDib schrieb:
Schieb mir doch die Datei mal per email rüber, dann sind wenigstens Zeichensatz-Ratespiele unnötig. Mailadresse kommt per PN.
Ich glaube, dass der Zeichensatz in diesem Fall keine Rolle spielt. Das hängt einfach nur mit der Anzeige zusammen. Eventuell "verschluckt" das Terminal ein paar Zeichen, wenn man die Ausgabe auf den Bildschirm schickt. Wenn man aber die Standardausgabe (STDOUT) in eine Datei umleitet, sind die Zeichen alle wieder da.

Als Hilfe kann man hier z.B. das utility hexdump nehmen...
Code:
~> script.pl <inputfile >outputfile
~> hexdump -Cv inputfile | tail -2
000006a0  61 73 68 32 30 3a db cd  d4 2a ee a5 78 2e 47 0a  |ash20:ÛÍÔ*î¥x.G.|
000006b0
~> hexdump -Cv outputfile | tail-2
00000650  30 3a db cd d4 2a ee a5  78 2e 47 0a              |0:ÛÍÔ*î¥x.G.|
0000065c
Ist alles noch da...
 
So ich bins nochmal. Könnt ihr mir nochmal helfen, ich kriegs irgendwie nicht hin, die Skripte so abzuändern, dass sie den umgekehrten Weg gehen, also von "D:\" zu "/45gb...", und alle "\" in den Pfaden zu "/". Da stören dann wohl die Doppelpunkte im "D;\".
 
Saber_Rider schrieb:
So ich bins nochmal. Könnt ihr mir nochmal helfen, ich kriegs irgendwie nicht hin, die Skripte so abzuändern, dass sie den umgekehrten Weg gehen, also von "D:" zu "/45gb...", und alle "" in den Pfaden zu "/". Da stören dann wohl die Doppelpunkte im "D;".
Nein! Da stören die Backlashes, weil die sowohl bei perl als auch in der Bash Meta-Zeichen sind. So sollte es gehen:
Code:
#!/usr/bin/perl

use strict;

my   $suche='D:\Downloads\Azureus_Torrents';
my $ersetze='/45gb_speicher/Downloads/Azureus_Torrents';

undef $/;      # gesamte Datei auf einmal lesen
$_=<STDIN>;    # von Standardeingabe lesen

my $length_diff=length($ersetze) - length($suche);  # Längendifferenz

$suche=~s/\\/\\\\/g;   # Backslashes maskieren

# Ersetzen
s/(\d+):$suche([^:]*)/$1+$length_diff . ":$ersetze" . &slash($2)/eg;

print;         # gesamte Datei auf einmal ausgeben

sub slash {       # konvertiere slash <--> backslash
  my $dir=$_[0];
  $dir=~tr#\\#\/#;
  return $dir;
}
 
@notoxp: Danke, werd ich später mal probieren, bin grad nicht daheim.

@SoeDib: Hab nur rumprobiert, und ein paar Sachen ersetzt. Hat aber nicht funktioniert. Und dann hab ich gleich alles was nicht ging gelöscht. Aber ich glaub ich müsste mich ernsthafter mit der Bash auseinandersetzen, damit ich das alles kapier. Das kommt aber noch, muss aber halt im Moment warten.
 
Moin Saber_Rider,
wie angekündigt, hab ich noch mal 'n bisschen mit deinem Skript rumgespielt. Rausgekommen ist jetzt ein Skript, das selbst erkennt, in welche Richtung konvertiert werden soll:
Code:
#!/bin/bash

#set -x    # Debugging toggle

# User Prefs
# Einfache Anführungszeichen !
linpath='/Daten/'
winpath='X:\'

if [ -r "$1" ] # Datei vorhanden?
then	export LC_COLLATE=POSIX
	config=$(sed -e 's/\([A-Z]\):\\/\1°°°°°\\/g' "$1") # dann einlesen und bearbeitbar machen
else	echo "Bitte (lesbare) zu konvertierende Datei angeben: \"$0 /pfad/zur/datei\""
	exit 1
fi

winp_q=${winpath/:/°°°°°}
winp_q=${winp_q//\\/\\\\}
linp_l=${#linpath} # Länge
winp_l=${#winpath}

if expr "$config" : '.*[0-9]\+:[A-Z]°°°°°' > /dev/null
then	# From Win to Lin
	path=winp_q
	newpath=linpath
	path_l_1=winp_l
	path_l_2=linp_l
	kn1='\\'
	kn2='/'
	ext=lin
else	# From Lin to Win
	path=linpath
	newpath=winpath
	winpath="$winpath\\"
	path_l_1=linp_l
	path_l_2=winp_l
	kn1='/'
	kn2='\\'
	ext=win
fi

path_diff_l=$((${!path_l_1}-${!path_l_2})) # Diff der Längen

while expr "$config" : '.*:' > /dev/null # wiederholen, solange noch Abschnitte übrig sind
do	key=${config%%:*} # Abschnitt einlesen...
	config=${config#*:} # ...und löschen
	if k=$(expr "$key" : '\(\(save_dir\|path\|torrent\)[[:digit:]]\+\)') # wenn Abschnitt="save_dirZZ", k=save_dirZZ
	then	# String für sed präparieren
		sedstr="${sedstr}
		s/${key}/${k%%[0-9]*}$((${k##*[a-z_]}-path_diff_l))/g"
		continue
	fi
	if expr "$key" : "${!path}" > /dev/null # Pfadersetzung nötig?
	then	# String für sed präparieren
		keynew=${key/${!path}/${!newpath}}
		keynew=${keynew//$kn1/$kn2}
		keyorig=${key/°°°°°/:}
		keyorig=${keyorig//\\/\\\\}
		#echo -e "$key:\n$keyorig --> $keynew"
		sedstr="${sedstr}
		s@${keyorig}@${keynew}@g"
	fi
done

if [ "$path_diff_l" -le 0 ]
then	_sort="sort -r"
else	_sort="sort"
fi
sedstr=$(echo "$sedstr"|${_sort}|uniq) # Kettenersetzungen(!) und unnütze Arbeit vermeiden
#echo "$sedstr"
sed -e "$sedstr" "$1" > "$1".$ext # Alles in einem Durchgang ersetzen und als "eingabedatei.[w|l]in" speichern
echo "Ergebnis als $1.$ext gespeichert."
Aufruf mit "./skriptname download.config".
Grüße,
SoeDib
 
Werds probieren, danke für die Mühe.
Und ja, ich verspreche mir mal anzusehen was ihr hier eigentlich genau gemacht habt ;-)
 
Oben