note 72644 added to function.copy

From: Date: Sat, 27 Jan 2007 16:20:42 +0000
Subject: note 72644 added to function.copy
Groups: php.notes 
Request: Send a blank email to php-notes+get-122267@lists.php.net to get a copy of this message
This function creates a new filename to use for a copy of the given filename, its behaviour was mostly sto^Wborrowed from how the OS X Finder (*1) does it. Note it *doesn't* actually copy the file, it just returns the new name. I needed it to work regardless of data source (filesystem, ftp, etc). It also tries to match the current name as neatly as possible: foo.txt -> foo copy.txt -> foo copy 1.txt -> foo copy 2.txt [etc] foo.bar.baz.jpg -> foo.bar.baz copy.jpg foobar -> foobar copy -> foobar copy 1 [etc] ".txt" -> .txt copy, and "txt." -> txt. copy file.longextension -> file.longextension copy It keeps trying until it finds a name that is not yet taken in $list, or until it looped 500 times (change as needed). If the renamed file becomes longer than max filename length, it starts chopping away at the end of the part before where it adds " copy": reallylong...filename.txt -> reallylong...filena copy.txt <?php // $orig = current name, of course // $list = array of filenames in the target directory (if none given, it will still return a new name) // $max = max length of filename function duplicate_name($orig, $list = array(), $max = 64) { $ext = ''; $counter = 0; $list = (array) $list; $max = (int) $max; $newname = $orig; do { $name = $newname; # name in, newname out if (preg_match('/ copy$| copy \d+$/', $name, $matches)) { // don't even check for extension, name ends with " copy[ digits]" // preg hereunder matches anything with at least one period in the middle (that is, // non-period characters on either side), and an extension of 1-5 characters }elseif (preg_match('/(.+)\.([^.]{1,5})$/', $name, $parts)) { // split to name & extension list($name, $ext) = array($parts[1], $parts[2]); } if (preg_match('/ copy (\d+)$/', $name, $digits)) { $newname = substr($name, 0, - strlen($digits[1])) . ($digits[1] + 1); # $cutlen is only used for the bit at the end where it checks on max filename length $cutlen = 6 + strlen($digits[1]+1); // ' copy ' + digits }elseif(preg_match('/ copy$/', $name, $digits)) { $newname = $name . ' 1'; $cutlen = 7; // ' copy' + ' 1' }else{ $newname = $name . ' copy'; $cutlen = 5; // ' copy' } if ($ext) { $newname .= '.' . $ext; $cutlen += strlen($ext) + 1; } if ($max > 0) { if (strlen($newname) > $max) { $newname = substr($newname, 0, max($max - $cutlen, 0)) . substr($newname, -$cutlen); if (strlen($newname) > $max) {echo "duplicate_name() error: Can't keep the new name under given max length.\n"; return false;} } } if ($counter++ > 500) {echo "duplicate_name() error: Too many similarly named files or infinite while loop.\n"; return false;} } while (in_array($newname, $list)); return $newname; } ?> *1) The Finder seems to check the extension vs a list of known extensions, this function considers it valid if it's 5 or fewer characters long. ps. sorry for taking up so much space! :-) ---- Server IP: 194.109.193.94 Probable Submitter: 82.73.63.123 ---- Manual Page -- http://www.php.net/manual/en/function.copy.php Edit -- https://master.php.net/note/edit/72644 Del: integrated -- https://master.php.net/note/delete/72644/integrated Del: useless -- https://master.php.net/note/delete/72644/useless Del: bad code -- https://master.php.net/note/delete/72644/bad+code Del: spam -- https://master.php.net/note/delete/72644/spam Del: non-english -- https://master.php.net/note/delete/72644/non-english Del: in docs -- https://master.php.net/note/delete/72644/in+docs Del: other reasons-- https://master.php.net/note/delete/72644 Reject -- https://master.php.net/note/reject/72644 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#122267) next »