Resolu : Renommer fichiers

Eléphanteau du PHP | 17 Messages

05 oct. 2011, 10:39

Bonjour

Je cherche a renommer les fichiers d'un repertoire donne, apres avoir eliminer certains caracteres speciaux, mais le script suivant bloque et je ne vois pas ou. Un peu d'aide serait la bienvenue :

Code : Tout sélectionner

<?php $tab_file = array(); function filter($in) { $search = array ('@[éèêëÊË]@i','@[àâäÂÄ]@i','@[îïÎÏ]@i','@[ûùüÛÜ]@i','@[ôöÔÖ]@i','@[ç]@i','@[ ]@i','@[^a-zA-Z0-9_]@'); $replace = array ('e','a','i','u','o','c','_',''); return preg_replace($search, $replace, $in); } $dirname = '/home/dev/smilies'; $dir = opendir($dirname); while($file = readdir($dir)) { if($file != '.' && $file != '..' && !is_dir($dirname.$file)) { $tab_tmp = explode(".", $file); $tab_file[$tab_tmp[0]] = $tab_tmp[1]; foreach($tab_file as $cle=>$valeur) { $rename_phrase = "rename(" . $dirname . "/" . $file .", " . $dirname . "/" . strtolower(filter($cle)) . "." . $valeur . ")\n"; rename($dirname . "/" . $file, $dirname . "/" . strtolower(filter($cle)) . "." . $valeur); } } } closedir($dir); ?>
La ou la "rename_phrase" m'affiche exactement ce que je veux faire, avec une bonne syntaxe, quand la fonction rename s'execute : elle fait n'importe quoi.. les noms de fichiers ne correspondent plus et elle ne parvient pas a trouver les fichier (no such file or directory :? ??? )

Merci
Modifié en dernier par baddev le 08 oct. 2011, 04:40, modifié 1 fois.
Le peu que je sais, c'est à mon ignorance que je le dois. Sacha Guitry

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

05 oct. 2011, 11:36

salut,

le ofreach n'a pas lieu d'être ici tu ne peux travailler sur un tableau, d'ailleur ton code n'est bon que pour des fichiers avec fichier.ext s'il contient un point c'est mort !

il faut prendre ce qu'il y a après le dernier point pour l'extension et tous ce qu'il y a avant pour le nom du fichier.

travail juste avec le while !

Perso j'ai fait ça pour php5 (à partir de la doc et ses commentaires), ça modifie l'extension mais bon c'est pas compliquer d'appliquer un changement sur le nom plutôt que l'extension ;)
<?php
$extensionfinal = '.php5';
$extensionoriginal = '.php';
$ite=new RecursiveDirectoryIterator('./');
$bytestotal=0;
$nbfiles=0;
echo '<pre>';
foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) {
    $filesize=$cur->getSize();
    $bytestotal+=$filesize;
    $nbfiles++;
	$sansextension = substr($filename,0, strrpos($filename,'.'));
	$extension = strrchr($filename,'.');
	if ($extension == $extensionoriginal){
		rename($filename,$sansextension.$extensionfinal);
		echo '<span>le fichier ', $filename ,' a été renommé en : ',$sansextension.$extensionfinal.'</span><br />';
	}
}
echo '</pre>';
$bytestotal=number_format($bytestotal);
echo "Total: $nbfiles files, $bytestotal bytes <br />";
?>
parcourt récursif des répertoires poru modifier l'extention des fichier des $extensionoriginal à $extensionfinal :)

@+
Il en faut peu pour être heureux ......

ViPHP
ViPHP | 2577 Messages

05 oct. 2011, 11:43

Bonjour,

Sauf erreur de ma part, ca devrait marché un peu mieux :
while($file = readdir($dir)) {
    if($file != '.' && $file != '..' &&) {
      $source = $dirname.'/'.$file;
      !is_dir($source)) {
      {
            $tab_tmp = explode(".", $file);
            if (count($tab_tmp) == 2) {
               $nom_cible = $tab_tmp[0];
               $extension_cible = $tab_tmp[0];
               $cible =  $dirname . "/".strtolower(filter($nom_cible)).$extension_cible;
               if (file_exists($cible) {
                   echo "rename impossible le fichier existe déjà : ",$source,'=>',$cible,"<br>\n";    
               } else {
                  if (rename($source,$cible))
                      echo "rename OK : ",$source,'=>',$cible,"<br>\n";
                  } else {
                      echo "rename KO : ",$source,'=>',$cible,"<br>\n";
                 }
              }
            } else {
                 echo "source incorrecte (plusieurs .): ",$source,"<br>\n";
           }
           } else {
                echo "répertoire : ",$source,"<br>\n";
           }
      }    
 }
Edit :
1) ma solution ne marche que pour les fichiers avec un seul . et ne traite pas les sous-répertoires.
2) Moogli connais beaucoup mieux que moi les subtilités de PHP.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

05 oct. 2011, 16:49

2) Moogli connais beaucoup mieux que moi les subtilités de PHP.
heu non, j'ai pris un bout de code que j'ai fait a partir de la doc parce que je trouvais soulant de devoir modifier l'extention des fichiers de mon site à la main juste pour changer de version de php (bon avant que je découvre que je pouvais changer la version utilisant l'extension .php dans l'interface que m'offre (enfin me loue plutot ^^) mon hébergeur :mrgreen: $

sinon n'étant pas sur mon ordi je ne peu tester le code fournit.

le !is_dir($source)) ne me plait pas (je ne sais pas si c'est fonctionnel, peux être j'en apprend tout les jours ;) ) mais un if me semble plus clair a la lecture ;)

@+
Il en faut peu pour être heureux ......

ViPHP
ViPHP | 5462 Messages

05 oct. 2011, 16:52

pour l'extension c'est soit avec pathinfo soit avec getExtension :wink:

si y'a Intl ca sera plus propre avec le Normalizer pour renommer les fichiers

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

05 oct. 2011, 17:11

pour l'extension c'est soit avec pathinfo soit avec getExtension :wink:

si y'a Intl ca sera plus propre avec le Normalizer pour renommer les fichiers
voui tiens faudrait que je modifie mon code mici du rappel.

pour Intl j'ai pas encore trouvé l’intérêt si j'aimais t'a un bout de doc sur le sujet ça peux m'intéresser :mrgreen:

@+
Il en faut peu pour être heureux ......

ViPHP
ViPHP | 5462 Messages

05 oct. 2011, 17:26

pour Intl j'ai pas encore trouvé l’intérêt si j'aimais t'a un bout de doc sur le sujet ça peux m'intéresser :mrgreen:

@+
$test = 'héhéhé';
$test = Normalizer::normalize($test, Normalizer::FORM_KD);
$test = preg_replace('/\p{Mn}+/u', '', $test);
echo $test;
// hehehe
après t'as l’outil pour les Traduction, et le formatage local de date et de nombre
un marrant :
$fmt = new NumberFormatter('fr', NumberFormatter::SPELLOUT );
echo $fmt->format(12345);
// douze-mille-trois-cent-quarante-cinq

Eléphanteau du PHP | 17 Messages

06 oct. 2011, 13:49

Bonjour

Tout d'abord, un grand merci a vous tous. Votre aide m'a ete d'un grand secours. :D

Apres une fausse joie, je crois maintenant avoir un script qui fonctionne. J'ai fait un mix de vos propositions, ca donne ca :
<?php

/*
/ Script normalisant les noms de fichiers d'un repertoire donne
/ Renomme les doublons
*/

// Repertoire par defaut
$dirname = "";

// Extension par defaut (au cas ou le fichier n'en ai pas)
$default_ext = "";

$tab_file = array();
$list_cle = array();

$bytestotal = 0;
$nbfiles = 0;
$n = 0;

function filter($in) {
	$search = array ('@[éèêëÊË]@i','@[àâäÂÄ]@i','@[îïÎÏ]@i','@[ûùüÛÜ]@i','@[ôöÔÖ]@i','@[ç]@i','@[ ]@i','@[^a-zA-Z0-9_]@');
	$replace = array ('e','a','i','u','o','c','_','');
	return preg_replace($search, $replace, $in);
}

$dir_iterator = new RecursiveDirectoryIterator($dirname);

foreach (new RecursiveIteratorIterator($dir_iterator) as $current_file)
{
    if($current_file != '.' && $current_file != '..' && !is_dir($dirname.$current_file))
    {
        $filesize = $current_file->getSize();
        $bytestotal += $filesize;
        $nbfiles++;
        
        $path_parts = pathinfo($current_file);
        $dirname_cf = $path_parts['dirname'];    
        $filename_cf = $path_parts['filename'];
        (array_key_exists('extension', $path_parts)) ? $extension_cf = $path_parts['extension'] : $extension_cf = $default_ext;
        
        if(strtolower(filter($filename_cf)) != "") $pot_rename =  $dirname_cf . "/" . strtolower(filter($filename_cf)) . "." . $extension_cf;
        
        if(file_exists($pot_rename))
        {
            echo "rename impossible, the file already exists : " . $current_file . " => " . $pot_rename . "\n";
            rename($current_file, $dirname_cf . "/" . strtolower(filter($filename_cf)) . "_" . $n . "." . $extension_cf);
            $n++;
        } else
        {
            if($current_file != ".")
            {
                rename($current_file, $pot_rename);
                echo "rename OK : " . $current_file . " => " . $pot_rename . "\n";
            } else
            {
                echo "A problem occured with this file : " . $current_file . "\nYou should verify your files, the script's exiting..\n\n";
                exit(1);
            }
        }
    }
}

// End of script
$bytestotal = number_format($bytestotal);
echo "\n\nTotal: $nbfiles files, $bytestotal bytes \n\n";


?>
C'est loin d'etre parfait mais ca fonctionne : ca renomme tous les fichiers (dans tous les cas de figures.. je crois :roll: ) et renomme aussi les doublons (independamment des extensions).

Par contre, je n'ai pas compris comment instancier Normalizer et j'ai aucune idee de ce que veut dire : '/\p{Mn}+/u'.. Si vous avex des idees pour l'ameliorer, n'hesitez pas ! :)

Encore merci ! ;)
Le peu que je sais, c'est à mon ignorance que je le dois. Sacha Guitry

ViPHP
ViPHP | 2577 Messages

06 oct. 2011, 14:13

@Moogli : je manque cruellement de culture concernant les trucs genre RecursiveIteratorIterator, j'ai la mauvaise habitude de réinventer la roue à chaque fois pour ce genre de chose. Au fil de mes lectures sur ce site, je me rends compte que tout une partie de PHP me manque comme les fonctions sur les tableaux. A ma décharge, je m'en passe très bien et j'en apprends tous les jours quand même. A ma décharge également, j'ai appris le PHP à partir des sources de PHPNUKE...

Mammouth du PHP | 2278 Messages

06 oct. 2011, 14:48

Et moi à partir de rien...
Mais la lecture de la doc, si mal faite soit-elle, encombrée des délires de programmeurs dont on ignore en général ce qu'ils font de la fonction qu'ils commentent et encore plus de la fonction qu'ils proposent, parfois juste (je suppose qu'elle fonctionne dans certains cas, mais j'ai l'expérience d'une bibliothèque fortran =>C qui proposait une pseudo inversion de matrices non-carrées qu'un étudiant désespéré me soumit: l'exemple fonctionnait, pas son appliacation, quand nous découvrimes que l'exemple était trafiqué... et la fonction, fort couteuse, inutilisable...)...
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ViPHP
ViPHP | 5462 Messages

06 oct. 2011, 15:05

if($current_file != '.' && $current_file != '..' && !is_dir($dirname.$current_file))
c'est isDot et isDir, faut lire la doc de temps en temps ca coute rien d’être curieux

Eléphanteau du PHP | 17 Messages

06 oct. 2011, 17:03

if($current_file != '.' && $current_file != '..' && !is_dir($dirname.$current_file))
c'est isDot et isDir, faut lire la doc de temps en temps ca coute rien d’être curieux
Merci pour tes suggestions : c'est vrai qu'apres une vingtaine de pages, j'avais un peu decroche. Je les avais loupe : my bad ! :roll:

En fait, normalizer retournait un not found : intl n'etait pas installer ! :lol:

La version 2.0 sera pour demain.. 8-)
Le peu que je sais, c'est à mon ignorance que je le dois. Sacha Guitry

Eléphanteau du PHP | 17 Messages

07 oct. 2011, 11:24

Voila la derniere mouture, le script fait ce qu'il doit faire et non plus par hasard.. Ce qui est un peu (voire beaucoup..) mieux, je reconnais. :)
<?php

/*
/ Script normalisant les noms de fichiers d'un repertoire donne
/ Renomme les doublons
*/

$dirname = "mypath";
$default_ext = "myextension";

$tab_files = array();
$list_double_key = array();

$bytestotal = 0;
$nbfiles = 0;
$n = 0;

function filter($in) {
	$search = array ('@[éèêëÊË]@i','@[àâäÂÄ]@i','@[îïÎÏ]@i','@[ûùüÛÜ]@i','@[ôöÔÖ]@i','@[ç]@i','@[ ]@i','@[^a-zA-Z0-9_]@');
	$replace = array ('e','a','i','u','o','c','_','');
	return preg_replace($search, $replace, $in);
}


try
{
    $iterator = new DirectoryIterator($dirname);
    
    foreach($iterator as $current_file)
    {
        if(!$current_file->isDot() && !$current_file->isDir())
        {
            // infos on $current_file
            $path_parts = pathinfo($current_file);
            $filename_cf = $path_parts['filename'];

            // register all filenames and extensions in an array for the doublet treatment
           $tab_files[] = $filename_cf;
        }
    }

    // write the doublets array
    $count = array_count_values(array_map('strtolower', $tab_files));
    foreach($count as $key=>$value)
    {
        if($value > 1)
        {
            $list_double_key[$key] = $value;
            //echo "nom = " . $key . " et nombre d'occurences = " . $value . "\n";
        }
    }
    
    foreach($iterator as $current_file)
    {
        if(!$current_file->isDot() && !$current_file->isDir())
        {
            // count files and their weight
            $filesize = $current_file->getSize();
            $bytestotal += $filesize;
            $nbfiles++;
            
            // infos on $current_file
            $path_parts = pathinfo($current_file);
            $filename_cf = $path_parts['filename'];
            // test if file has an extension, if not assign the default one        
            (array_key_exists('extension', $path_parts)) ? $extension_cf = $path_parts['extension'] : $extension_cf = $default_ext;
            
            // test if normalized filename is empty
            if(strtolower(filter($filename_cf)) != "") $pot_rename =  $dirname . strtolower(filter($filename_cf)) . "." . $extension_cf;
            
            if(file_exists($pot_rename))
            {
                // test renaming relevance
                $supposed_file = strtolower(filter($filename_cf)) . "." . $extension_cf;
                $supposedn_file = strtolower(filter($filename_cf)) . "_" . $n . "." . $extension_cf;
                if($supposed_file == $current_file)
                {
                    if(array_key_exists($filename_cf, $list_double_key))
                    {
                        echo "There is some other file with the same name but another extension : renaming !\n";
                        rename($dirname . $current_file, $dirname . "/" . $supposedn_file);
                        echo "\tactually rename to : " . $current_file . " => " . $supposedn_file . "\n";
                        $n++;
                    }else
                    {
                        echo $current_file . " is already normalized : nothing to do.\n";
                    }
                } else
                {
                    echo "rename impossible, the file already exists : " . $current_file . " => " . $supposed_file . "\n";
                    rename($dirname . $current_file, $dirname . "/" . $supposedn_file);
                    echo "\tactually rename to : " . $current_file . " => " . $supposedn_file . "\n";
                    $n++;
                }
            } else
            {
                rename($dirname . $current_file, $pot_rename);
                echo "rename OK : " . $current_file . " => " . strtolower(filter($filename_cf)) . "." . $extension_cf . "\n";
            }
        }
    }
    
    // End of script
    $bytestotal = number_format($bytestotal);
    echo "\n\nTotal: $nbfiles files, $bytestotal bytes \n\n";

} catch(Exception $e)
{
    echo "A problem occured : The script\'s exiting !";
}

?>
Un grand merci a stealth35 qui aura su repousse les limites de l'exigence ! :D
Le peu que je sais, c'est à mon ignorance que je le dois. Sacha Guitry

ViPHP
ViPHP | 5462 Messages

12 oct. 2011, 12:12

ça me parait bien compliquer tout ça,
t'as un exemple de liste de fichier en entrée avec la sortie que ça rend ?

Eléphanteau du PHP | 17 Messages

12 oct. 2011, 12:42

Avant :

00076079.jpg
1email.gif
ABOUT.BMP
action.gif
angeldivider.gif
angry.BMP
^&*$$%.gif

Apres :

00076079.jpg
_0.gif
1email.gif
about.BMP
action.gif
angeldivider.gif
angry.BMP

Si tu as plus simple, n'hesites pas : j'ai le developpement ouvert.. :D
Le peu que je sais, c'est à mon ignorance que je le dois. Sacha Guitry