Archiv verlassen und diese Seite im Standarddesign anzeigen : Dateinamen kürzen
DaHintenSitzeIch
09.03.2008, 20:23
Guten Abend, ich muss 19.000 Dateien umbenennen und zwar so, dass der Dateiname nicht länger als 12 Zeichen ist. Die 5-stellige lfd. Nr. behalte ich bei, von den Wörtern möchte ich immer nur den Anfangsbuchstaben benutzen, also aus
00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN
soll werden
00305_IMDSLN
Im Original sind die Dateinamen ziemlich unterschiedlich lang. Mal mit 1 oder 2 Wörtern, mal mit 20.
Kann man das mit RegEx lösen und wie sähe der Code aus?
Gruß
Thomas
wenn du nur solche dateinamen hast, würde ich ohne reguläre ausdrücke arbeiten.
du musst doch im prinzip nur einen string mit 12 zeichen erstellen, die ersten 5 ziffern jeweils hineinkopieren und dann nach jedem leerzeichen das zeichen anfügen.
mal in php:
<?php
function shortenfilename( $filename )
{
$ret = substr( $filename, 0, 5 ).'_';
for( $i = 5; $i < strlen( $filename ) && strlen( $ret ) < 12; $i++ )
if( ' ' == $filename[$i-1] )
$ret .= $filename[$i];
return $ret;
}
?>
00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN -> 00305_IMDSLN
00212 DAS IST EIN WEITERER TEST STRING -> 00212_DIEWTS
01826 DIESER STRING SOLL EBENFALLS GEKÜRZT WERDEN -> 01826_DSSEGW
89172 UND WIEDERUM EIN STRING DER GENAUSO GEKÜRZT WERDEN SOLL -> 89172_UWESDG
98132 TEST DATEI -> 98132_TD
wesentlich kürzer und effizienter :)
Firefall
09.03.2008, 21:16
(\d{5})([A-Za-z])[A-Za-z]* ([A-Za-z])[A-Za-z]* ([A-Za-z])[A-Za-z]* ([A-Za-z])[A-Za-z]* ([A-Za-z])[A-Za-z]* ([A-Za-z])[A-Za-z]*
Würde ich als Suchmuster verwenden. Anschliessend lautet der Dateiname:
$1_$2$3$4$5$6$7, wobei $1 bis $7 die Submatches 1 bis 7 darstellen sollen (Respektiv 0 bis 6).
eViL_oNe
10.03.2008, 00:49
höchst problematisch das ganze!
was machst du, wenn zufällig zwei Namen zusammenfallen? Ich würde das Ganze wie claw vorgeschlagen hatte, mit Substring-Spielereien lösen und um einen Zusatzalgorithmus ergänzen:
1. Sofern der Dateiname schon existiert, hänge einen index an den Namen heran, ala "_<nummer>"
2. Setze das ganze solange fort, bis eine freie Nummer gefunden wurde.
PS: das Verfahren von Firefall hat einen entscheidenden Schwachpunkt: es findet kein Match statt, falls sich der String nicht auf die beschriebene Länge reduzieren lässt (etwa weil weniger als Leerzeichen enthalten sind oder wenn die Wörter etwas anderes als einen Buchstaben am Anfang haben oder gar mehrere Leerzeichen hintereinander vorkommen). Das lässt sich zwar alles kompensieren, dann wird aber der Ausdruck etwas komplizierter ;)
PS2: das Problem mit mehrfachen Leerzeichen gibt es auch bei claw
die Lösung davon wäre wohl:
function shortenfilename( $filename )
{
$ret = substr( $filename, 0, 5 ).'_';
// use an inner state to indicate if the next character should be appended
$appendNextChar = false;
for( $i = 5; $i < strlen( $filename ) && strlen( $ret ) < 12; $i++ )
if( ' ' == $filename[$i] )
{
// we have detected a white space. Thus the next non-whitespace character should be appended to our return string
$appendNextChar = true;
}
if ( $appendNextChar && $filename[$i] != ' ' )
{
// append the character and reset our inner state
$ret .= $filename[$i];
$appendNextChar = false;
}
return $ret;
}
bin jetzt zu faul das ganze zu testen, solle aber eigentlich gehen ;)
Das ganze sollte wie gesagt noch um eine Existenzprüfung des Resultats erweitert werden, am besten als separater Code abseits dieser Methode ;)
DaHintenSitzeIch
10.03.2008, 11:01
Moin, Moin,
danke für die Hilfe. Ich habe mich für die PHP-Lösung entschieden, da der von Firefall beschriebene reguläre Ausdruck bei kurzen Dateinamen im FlexRenamer nicht funktioniert.
Da ich gerade ein wenig mit RegEx experimentiere würde mich folgendes interessieren: Was muss ich ändern, damit auch der kurze String gefunden wird (siehe Anhang)?
(\d{5})[ _]([\w])[\w]*[ _]([\w])[\w]*[ _]([\w])[\w]*
Mein PHP-Code, der die knapp 20000 Files Amiga-Tauglich gemacht hat
<?php
function shortenfilename( $filename )
{
$ret = substr( $filename, 0, 5 ).'_';
for( $i = 5; $i < strlen( $filename ) && strlen( $ret ) < 12; $i++ )
if( ' ' == $filename[$i-1] )
$ret .= $filename[$i];
return $ret;
}
$path = "D:/TEMP";
$dh = opendir($path);
while (($file = readdir($dh)) !== false) {
if($file != "." && $file != "..") {
$endung = substr($file, strrpos($file, "."));
echo "<p>".$path."/".$file."<br />==>".$path."/".shortenfilename($file).$endung."</p>";
//ENTKOMMENTIER MICH UND ICH BIN SCHARF :-)
//rename($path."/".$file, $path."/".shortenfilename($file).$endung);
}
}
closedir($dh);
?>
BrudaSwen
10.03.2008, 11:54
Ich hätte das ganze per split gelöst, was das ganze etwas übersichtlicher macht:
function shortenfilename($filename) {
$words = split(' +', $filename, 7);
$ret = $words[0].'_';
for($i=1; $i < count($words); $i++) {
$ret .= $words[$i][0];
}
return $ret;
}
BrudaSwen
10.03.2008, 12:29
Da ich gerade ein wenig mit RegEx experimentiere würde mich folgendes interessieren: Was muss ich ändern, damit auch der kurze String gefunden wird (siehe Anhang)?
(\d{5})[ _]([\w])[\w]*[ _]([\w])[\w]*[ _]([\w])[\w]*
So hat es testweise funktioniert:
(\d{5})(?: +(\w)\w+)(?: +(\w)\w+)?(?: +(\w)\w+)?(?: +(\w)\w+)?(?: +(\w)\w+)?(?: +(\w)\w+)?.*
preg_replace("!(\d{5})(?: +(\w)\w+)(?: +(\w)\w+)?(?: +(\w)\w+)?(?: +(\w)\w+)?(?: +(\w)\w+)?(?: +(\w)\w+)?.*!", "$1_$2$3$4$5$6$7", "00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN");
// 00305_IMDSLN
hier das ganze mal mit sämtlichen drum und dran:
<pre>
<?php
$str = array(
'00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN',
'00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN',
'00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN',
'00305 ICH MÖCHTE DIESEN SEHR LANGEN NAMEN ZERLEGEN',
'00212 DAS IST EIN WEITERER TEST STRING',
'01826 DIESER STRING SOLL EBENFALLS GEKÜRZT WERDEN',
'89172 UND WIEDERUM EIN STRING DER GENAUSO GEKÜRZT WERDEN SOLL',
'98132 TEST DATEI'
);
function shortenfilename( $filename )
{
$parts = explode( ' ', $filename );
$ret = '';
$ret .= $parts[0].'_';
for( $i = 1; $i < sizeof( $parts ) && strlen( $ret ) < 12; $i++ )
$ret .= $parts[$i][0];
return $ret;
}
function newfilename( $filename, $padlen = 3 )
{
if( !file_exists( $filename ) ) return $filename;
$f = $filename;
$format = $filename.'_%s';
$i = 1;
while( file_exists( $f ) )
{
++$i;
$f = sprintf( $format, str_pad( $i, $padlen, '0', STR_PAD_LEFT ) );
}
return $f;
}
foreach( $str as $s )
{
$fh = fopen( './'.newfilename( shortenfilename( $s ) ), 'w' );
fclose( $fh );
echo './'.newfilename( shortenfilename( $s ) )."\n";
}
?>
</pre>
ausgabe der dateien wäre dann z.b.:
00212_DIEWTS
00212_DIEWTS_002
00212_DIEWTS_003
00305_IMDSLN
00305_IMDSLN_002
00305_IMDSLN_003
00305_IMDSLN_004
00305_IMDSLN_005
00305_IMDSLN_006
00305_IMDSLN_007
00305_IMDSLN_008
00305_IMDSLN_009
00305_IMDSLN_010
00305_IMDSLN_011
00305_IMDSLN_012
01826_DSSEGW
01826_DSSEGW_002
01826_DSSEGW_003
89172_UWESDG
89172_UWESDG_002
89172_UWESDG_003
98132_TD
98132_TD_002
98132_TD_003
ausgabe der dateien wäre dann z.b.:
In deinem Beispiel sind jetzt einige Dateinamen 16 Zeichen lang.
Firefall
10.03.2008, 21:27
Jep, wenn du die Nummer anhängst musst du (die letzten) 4 Zeichen löschen. Und dass die Nummer auf 3 Stellen beschränkt ist, könnte auch noch zum Problem werden ;)
Jep, wenn du die Nummer anhängst musst du (die letzten) 4 Zeichen löschen. Und dass die Nummer auf 3 Stellen beschränkt ist, könnte auch noch zum Problem werden ;)
die 3 hab ich nur gewählt da ich nicht weiß wieviel dateien beinhaltet werden. es kann ja gut möglich sein, dass er > 1000 dateien so kürzen will und 100+ davon asd heißen. was machst du dann mit der 101. datei? bei 0 anfangen geht nicht, 99 ist auch belegt - ohne nummer ebenso. also wird wohl eine datei überschrieben und das ist es ja nicht was man damit haben will.
es ist außerdem nur ein beispiel: selbst ist der mann! ;)
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.