Windows : Remplacer un fichier par un autre

Il me semble que @Kip veut les versionner en plus si on lit son texte et la réponse d’@Ewi.

Ah super merci. Je ne connais pas bash donc j’ai regardé sur le net et ok. Moi je pensais à une solution directement dans le shell, sans rien avoir à modifier ou installer. Finalement là ça revient au même qu’avec le script de @Ewi avec lequel il faut installer Python. Du coup quelle est la solution la plus perenne ? Genre dans 4-5 ans, quel script marchera toujours ?

Sur Windows Powershell est la solution la plus perenne qui ne nécessite pas d’installer quoi que ce soit. Le script fait la même longueur. Je regarde pour te l’écrire si tu es intéressé.

Et plus généralement, et même si on est sur le forum du « installe Linux », Powershell s’est bien. Au lieu de manipuler des chaînes de caractère tu bosse avec des objets qui sont tes fichiers et on des attributs (chemin, nom du fichier, date de création, …). Je ne suis pas toujours fan de la syntaxe mais c’est propre.

surement le powershell :

$dir = 'c:\path\to\dir'
$newFile = 'c:\path\to\file'
$oldName = "fileV2.pdf"
$files = Get-ChildItem -Path $dir -Recurse
ForEach ($file In $files)
{
    If ($file.Name -eq $oldName)
    {
        Write-Host 'Replacing:'$file.FullName
        Copy-Item -Path $newFile -Destination $file.FullName -Force
    }
}

(j’ai pas testé, j’ai fait de tete. Mon admin ne nous autorise pas a utiliser powershell, mais tu peux en copiant/collant le code dans un fichier .ps1)

1 « J'aime »

Tu peux ajouter un filtre sur le Get-ChildItem pour t’économiser le test.
Perso je l’écris plus comme ça (pas testé non plus) :

$dir = 'c:\path\to\dir'
$newFile = 'c:\path\to\file'
$oldName = "fileV2.pdf"
$files = Get-ChildItem -Path $dir -Recurse -Filter $oldName
$files | ForEach-Object {    
     Write-Host 'Replacing:'$_.FullName
     Copy-Item -Path $newFile -Destination $_.FullName -Force 
}

Tu peux même rajouter un switch -File pour éviter de chercher les répertoires.

$dir = 'c:\path\to\dir'
$newFile = 'c:\path\to\file'
$oldName = "fileV2.pdf"
$files = Get-ChildItem -Path $dir -Recurse -Filter $oldName -File
$files | ForEach-Object {    
 Write-Host 'Replacing:'$_.FullName
 Copy-Item -Path $newFile -Destination $_.FullName -Force 
}
1 « J'aime »

Merci pour vos réponse. Le script se lance bien et on voit apparaitre la ligne qui dit que la fichier a été remplacé. Mais spoiler : le fichier n’a pas été remplacé. Rien n’a changé et tout est à sa place.

tu as lu mon post?

Oui mais c’est pas du tout cette commande qui va marcher, cf mon post de départ et la suite de la discussion.

oui mais la question reste la meme :slight_smile:

  • est-ce tu veux remplacer le contenu de tous les file-v1.pdf par celui de file-v2.pdf en laissant en place les file-v1.pdf ?
  • ou tu veux effacer tous les file-v1.pdf et copier au même emplacement des file-v2.pdf ?

J’avais mal compris. La 2ème option, l’idée est que les anciens fichiers disparaissent (file-v1.pdf) et que je me retrouve uniquement avec les nouveaux fichiers (file-v2.pdf).

https://ss64.com/nt/for.html

ok, ca donnerait ca du coup en shell:

find /path/to/directory -type f -name file-v1.pdf -exec sh -c 'cp -fpr /path/to/file/file-v2.pdf "$(dirname "$1")"/' sh {} ';' -exec rm {} \;

Et pour répondre aux questions:
« pourquoi dans ton 1er exec tu utilises une syntaxe différente d’auparavant? »: j’ai jamais réussi à faire un dirname de {} … ca me donne tout le temps le repertoire courant.
« pourquoi tu as mis 2 exec alors que t’aurais pu mettre ton rm dans le 1er? »: parceque le 2eme exec n’est effectué que si le 1er s’est fini avec succès. On s’assure donc de ne pas effacer le fichier original si la copie ne se passe pas bien.

sauf qu’il faut activer le terminal linux avant :slight_smile:

Ou tout au moins installer un bash pour Windows.

(Le plus simple à installer étant celui fourni avec Git pour Windows https://gitforwindows.org/)

encore plus simple il est inclus dans win10 maintenant, dans les options logicielles

Ouais, c’est une case à cocher et ça simplifie tellement la vie…

Sinon, en .bat, sans rien besoin d’installer.

cls
echo off
set OLD_FILE=toto-old.txt
set NEW_FILE=toto-new.txt
set BASE_PATH=D:\Videos\

For /f "tokens=*" %%G IN ('dir /b /s /a:d "%BASE_PATH%*"') do (

echo Working in %%G

echo Copying %BASE_PATH%%NEW_FILE% to %%G\%NEW_FILE%
copy %BASE_PATH%%NEW_FILE% %%G\%NEW_FILE%

echo Deleting old file : %%G\%OLD_FILE%
del %%G\%OLD_FILE%

echo.

)

pause
4 « J'aime »

par contre

pas de " " pour la copy? si son fichier ou ses reps ont des espaces il ne va pas aimer?

Non, parce qu’en 5min j’ai pas cherché a faire mieux, mais en effet.