Friends, I need to rename pdf files to a certain standard. For that I made the following script:
c:
cd \importation
if not exist %1 goto end
md %~n1
move %1 %~n1\P%~n1_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %2 goto end
md %~n2
move %2 %~n2\P%~n2_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %3 goto end
md %~n3
move %3 %~n3\P%~n3_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %4 goto end
md %~n4
move %4 %~n4\P%~n4_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %5 goto end
md %~n5
move %5 %~n5\P%~n5_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %6 goto end
md %~n6
move %6 %~n6\P%~n6_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %7 goto end
md %~n7
move %7 %~n7\P%~n7_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %8 goto end
md %~n8
move %8 %~n8\P%~n8_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %9 goto end
md %~n9
move %9 %~n9\P%~n9_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
:end
It turns out that the script only modifies up to 9 files at a time. Does anyone know how I can make this change to all files in the folder? Sometimes there are 100,200 or even more pdfs
Use Get-ChildItem to discover the files, then inspect their BaseName property to get the file name without the extension:
$rootFolder = 'C:\importation'
Get-ChildItem $rootFolder -File -Filter *.pdf |ForEach-Object {
# create new folder
$newFolder = mkdir -Path $rootFolder -Name $_.BaseName
# construct target path
$targetPath = Join-Path $newFolder.FullName "P$($_.BaseName)_V1_A0V0_T07-54-369-664_S00001_Volume.pdf"
# move file
$_ |Move-Item -Destination $targetPath
}
This should work
# Define variables
$Folder = "C:\myfolder"
$OldFileName = "OldFileName1.pdf"
$NewFileName = "NewFileName1.pdf"
# Get all files in the folder non-recursively
$Files = Get-ChildItem $Folder
# For each file
foreach ($File in $Files){
# If file matches the OldFileName
If ($File.Name -eq $OldFileName){
# Rename the file to the new name
Rename-Item -Path $File.FullName -NewName $NewFileName
}
}
Related
I use this script to move a set of files inside folders generated by script
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=C:\Users\Administrator\Desktop\khin\test"
SET "destdir=C:\Users\Administrator\Desktop\khin\test"
SET /a destcount=0
SET /a maxcount=10
SET /a filecount=maxcount
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
SET /a filecount +=1
IF !filecount! geq %maxcount% (
SET /a filecount=0
SET /a destcount +=1
MD "%destdir%\folder!destcount!"
)
MOVE "%sourcedir%\%%a" "%destdir%\folder!destcount!\"
)
GOTO :EOF
What is my problem?
I need always to set a source folder and a target folder
SET "sourcedir=C:\Users\Administrator\Desktop\khin\test"
SET "destdir=C:\Users\Administrator\Desktop\khin\test"
What do I want?
I want just press on batch .bat (is inside into my folder) where files are ready to be moved without set source/target because I have to repeat this operation for other files in other folders as well.
example:
I have 31 files (example). I execute this script and script creates 3 folders. For each folder you find 10 files (except in the fourth folder where you will find 1 file).
To do this, my script need to have source and target to move files. But I want that script generates these folders inside the folder it is in.
If you could do this in PowerShell, it might be something like this. Note that this will -not move the .ps1 script file.
$MaxCount = 10
$FileList = Get-ChildItem -File -Path $(Split-Path -Path $PSCommandPath -Parent) |
Where-Object { $_.Name -ne $(Split-Path -Path $PSCommandPath -Leaf) }
for ($i = 0; $i -lt $FileList.Count; $i++) {
$DirNum = [Math]::Floor($i / $MaxCount)
$DirName = Join-Path -Path $(Split-Path -Path $PSCommandPath -Parent) `
-ChildPath $("Dir" + $DirNum)
if (-not (Test-Path $DirName)) { mkdir $DirName -WhatIf }
Move-Item -Path $Filelist[$i].FullName -Destination $DirName -WhatIf
}
I have a file by the name yyyymmddFile1.txt where date prefix is added in a particular format.
I need to copy that file from one location to another and I need to pick today's and yesterday's file
For today, I wrote
SET TODAY=%date:~10,4%%date:~4,2%%date:~7,2%
SET MAINPATH=D:\%TODAY%File1.txt
if exist %MAINPATH% (
COPY D:\%TODAY%File1.txt D:\NDM\InFileQueue\%TODAY%File1.txt
)
so, This will set the filename to 20190502File1.txt
But I can't figure out how to pass yesterday's date as a variable. I need to do something like this -
SET YESTERDAY= ??
SET MAINPATH=D:\%YESTERDAY%File1.txt
if exist %MAINPATH% (
COPY D:\%YESTERDAY%File1.txt D:\NDM\InFileQueue\%YESTERDAY%File1.txt
)
You can incorporate vbs and get a proper date format.Here you simply have to change the value of set day=-1 to toggle the number of days you want to remove from today's date.
#echo off
set day=-1
echo >"%temp%\%~n0.vbs" s=DateAdd("d",%day%,now) : d=weekday(s)
echo>>"%temp%\%~n0.vbs" WScript.Echo year(s)^& right(100+month(s),2)^& right(100+day(s),2)
for /f %%a in ('cscript /nologo "%temp%\%~n0.vbs"') do set "result=%%a"
del "%temp%\%~n0.vbs"
set "yyyy=%result:~0,4%"
set "mm=%result:~4,2%"
set "dd=%result:~6,2%"
set "final=%yyyy%%mm%%dd%"
echo Just doing an echo to screen of %final% for testing.
set "MAINPATH=D:\%final%File1.txt"
if exist %MAINPATH% (
copy D:\%final%File1.txt D:\NDM\InFileQueue\%final%File1.txt
)
To expand a little on my comment…
For files from both today and yesterday as a batch-file:
#Set "Src=D:\."
#Set "Dst=D:\NDM\InFileQueue"
#Set "Ext=.txt"
#RoboCopy "%Src%" "%Dst%" "*%Ext%" /MaxAge:2 > Nul
Or as a single command from either cmd.exe or a batch-file, (prepend the line with # to turn off its echoing if your wish):
RoboCopy "D:\." "D:\NDM\InFileQueue" "*.txt" /MaxAge:2 > Nul
For files from yesterday only, (ignoring todays), as a batch-file:
#Set "Src=D:\."
#Set "Dst=D:\NDM\InFileQueue"
#Set "Ext=.txt"
#RoboCopy "%Src%" "%Dst%" "*%Ext%" /MaxAge:2 /MinAge:1 > Nul
Or as a single command from either cmd.exe or a batch-file, (prepend the line with # to turn off its echoing if your wish):
RoboCopy "D:\." "D:\NDM\InFileQueue" "*.txt" /MaxAge:2 /MinAge:1 > Nul
You will note that there is one oddity, D:\., RoboCopy doesn't like the source or destination paths to end with a trailing backslash, so when one of them is the root of a drive, e.g. D:\, it is necessary to add the period, (you cannot use D:). Non root drive sources and destinations would simply use the path as I have in the example above for %Dst%.
Another way would be to use PowerShell. When you are satisfied that the files will be copied correctly, remove the -WhatIf switches.
=== get2files.ps1
$sourcedir = 'C:/the/original/directory'
$destinationdir = 'C:/the/new/directory'
$filetoday = (Join-Path -Path $sourcedir -ChildPath (Get-Date -Format yyyyMMdd)) + 'File1.txt'
$fileyesterday = (Join-Path -Path $sourcedir -ChildPath (Get-Date (Get-Date).AddDays(-1) -Format yyyyMMdd)) + 'File1.txt'
if (Test-Path -Path $filetoday) { Copy-Item -Path $filetoday -Destination 'C:/the/new/directory' -WhatIf }
if (Test-Path -Path $fileyesterday) { Copy-Item -Path $filetoday -Destination 'C:/the/new/directory' -WhatIf}
=== get2files.bat
powershell -NoLogo -NoProfile -File "%~dp0get2files.ps1"
I am using below batch script to copy .class files from dir sourcedir2 to dir sourcedir1 based on same matched file names.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir1=U:\sourcedir\changeset"
SET "sourcedir2=U:\sourcedir\target"
FOR /f "delims=" %%a IN ('dir /b /s /a-d "%sourcedir1%\*.java" ') DO (
SET "javadir=%%~dpa"
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na.class"
IF EXIST !classfile! ECHO COPY "!classfile!" "%%a"
)
GOTO :EOF
Addition to this I wanted to copy .class files which are having filename format as classname$number.class (ex :Action$1.class ,Action$2.class) from dir sourcedir2 to dir sourcedir1.
I tried the change for SET classfile as below but also it will copy files which are not in the format of classname$number.class
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na*.class"
Please suggest me Regularexpression to match file names with having only format as classname$number.class or classname.class .
Thank you ..
This PowerShell script copies from sourcedir2 to sourcedir1 based on the filename matching a regex for the class name and any digits before the .class extension. When you are confident that the correct files will be copied, remove the -WhatIf from the Copy-Item cmdlet.
$sourcedir1 = 'C:\src\t\j1'
$sourcedir2 = 'C:\src\t\j2'
Get-ChildItem -Path $sourcedir1 -File -Recurse -Filter '*.java' |
ForEach-Object {
$classname = $_.BaseName
Get-ChildItem -Path $sourcedir2 -File -Filter "$classname*.class" |
Where-Object { $_.Name -match "$classname\$[0-9]*\.class" } |
ForEach-Object { Copy-Item $_.FullName $sourcedir1 -WhatIf }
}
To run this from a cmd shell, put the code above into a file such as copyclasses.ps1 and use:
powershell -NoProfile -File .\copyclasses.ps1
I am able to find the workaround solution with below script. Thank you.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir1=U:\sourcedir\changeset"
SET "sourcedir2=U:\sourcedir\target"
FOR /f "delims=" %%a IN ('dir /b /s /a-d "%sourcedir1%\*.java" ') DO (
SET "javadir=%%~dpa"
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na.class"
IF EXIST !classfile! ECHO COPY "!classfile!" "%%a"
SET "innerclassfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na"$"*.class"
IF EXIST !innerclassfile! ECHO COPY "!innerclassfile!" "%%a"
)
GOTO :EOF
Ok,
I have multiple text files that will be coming into a folder that I am processing into a single output file. The batch will run every few hours.
for %%f in (*.txt) do type "%%f" >> ESOComplete\ESOInput.txt
This will copy all text from text files to one single text file in another subfolder.
From there I need one to move all files (Example 510002.txt) to a subfolder called ESOMoved. Leaving the root folder empty so next time the batch runs it doesn't add the same data to the ESOInput.txt
Now, I need the batch file that moves the orignal data from the root to not overwrite, so if files already exists I want it to rename it (From 510002.txt to 5100022.txt)
In the end it should be
1. Move all text from all .txt documents to one output file. (Which is already done)
2. Move all .txt documents to subfolder called ESOMoved, unless that specific document already exists, in which case rename, and then move.
EDIT
If the file with the appended 2 already exists the number is increased until it is free.
#Echo off
:: Start in base folder
PushD "Q:\Test\2017\07\22"
for %%f in (??????.txt) do (
type "%%f" >> "ESOComplete\ESOInput.txt"
If Not Exist "ESOMoved\%%f" (
Move "%%f" "ESOMoved\"
) Else (
Set Num=2
Call :Move "%%f"
)
)
PopD
Goto :Eof
:Move
Set "NewName=ESOMoved\%~n1%Num%%~x1"
If Not Exist "%NewName%" (
Echo Move %1 "%NewName%"
Move %1 "%NewName%" >Nul 2>&1
Exit /B 0
)
Set /A Num+=1
Goto :Move
The trick to this is devising a renaming scheme. The code below appends "-N" to the file basename to create a unique file it will keep incrementing N until if finds a filename that does not exist.
Save this file as esomover.ps1.
$files = Get-ChildItem -Path 'C:/src/t/ESO/' -File -Filter 'file*.txt'
$sum_file = 'C:/src/t/ESO/ESOComplete/ESOInput.txt'
$arch_dir = 'C:/src/t/ESO/ESOArchive'
if (-not (Test-Path -Path $sum_file)) { New-Item -Path $sum_file -ItemType File }
foreach ($file in $files) {
Add-Content -Path $sum_file -Value (Get-Content $file.FullName) -Encoding Ascii
if (-not (Test-Path "$($arch_dir)/$($file.Name)")) {
Move-item $file.FullName $arch_dir
} else {
$i = 0
$nfn = ''
do {
$nfn = "$($file.BaseName)-$($i.ToString()).txt"
$i++
} while (Test-Path -Path "$($arch_dir)/$($nfn)")
Move-Item $file.FullName "$($arch_dir)/$($nfn)"
}
}
Run this script from a cmd.exe shell or .bat file using:
powershell -noprofile -file .\esomover.ps1
I'm trying to combine two directories on a Windows 7 machine that have some of the same subfolders (but not all) and some of the same files (but not all). I'd like to copy
For example, I have the following directory structure and want to combine (copy or move) "Dir_A" and "Dir_Z". Where the file exists in the destination directory, I want to compare filesizes and keep the larger of the two files.
Dir A
Dir B
file 1.txt
file 2.txt
file 3.txt
Dir C
file 4.txt
Dir D
file 5.txt
file 6.txt
Dir_Z
Dir Y
file 8.txt
Dir C
file 4.txt
Dir D
file 6.txt
I'm comfortable using a cmd file or powershell. Thank you in advance.
EDIT: Modify to include spaces in the director and file names and add what I have so far.
Here's what I've been able to do so far. It appears to work with the exception of when there are spaces in the directory or filenames.
#echo off
echo :: Combine two folders, Keep the larger of any given files, Delete the other
if "%1"=="" goto :NoParam
if "%2"=="" goto :NoParam
setlocal enabledelayedexpansion
set SOURCE_DIR=%1
set DEST_DIR=%2
for /R "%SOURCE_DIR%" %%S in (*) do (
echo Source: "%%S"
#echo off
for /f "delims=" %%R in ('call MakeRelative.cmd "%%S" "%SOURCE_DIR%"') do (
set FILE_REL="%%R"
set filename=%DEST_DIR%\%%R
For %%D in ("!filename!") do (
Set Name=%%~nxD
if exist %DEST_DIR%\%%R (
echo File Exists
if %%~zD lss %%~zS (
echo Destination %%~zD is smaller than Source %%~zS
call robocopy %%~dpS %%~dpD "!Name!" /MOV
) else del %%S && Echo File is not larger, Deleting %%S
) else call robocopy %%~dpS %%~dpD "!Name!" /MOV
)
)
)
Pause
goto :eof
:NoParam
echo.
echo Syntax: %0 [Source_DIR] [Dest_DIR]
goto :eof
I make use of the MakeRelative.cmd as outlined here: http://www.dostips.com/DtCodeCmdLib.php#MakeRelative
I apologize that this is not elegant.
I'm not much of a PowerShell developer, but this should do the work and is hopefully somewhat more obvious regarding what it's doing than the batch file.
if($args.length -ne 3) {
"usage: PowerShell ThisScriptName.ps1 -command ""SourceDirectory"" ""DestinationDirectory""";
Exit
}
function CopyFileIfSourceIsLarger($SourceFile, $DestinationFile) {
$S = New-Object IO.FileInfo($SourceFile.ToString());
$D = New-Object IO.FileInfo($DestinationFile.ToString());
if ($S.Length -gt $D.Length ) {
"Overwriting smaller file " + $D.FullName;
[IO.File]::Copy($S.FullName, $D.FullName, $true);
}
}
$SourceDir = New-Object IO.DirectoryInfo($args[1]);
$DestinationDir = New-Object IO.DirectoryInfo($args[2]);
$SourceDirectoryPath = $SourceDir.FullName;
$DestinationDirectoryPath = $DestinationDir.FullName;
"Source Path: " + $SourceDirectoryPath;
"Destination Path: " + $DestinationDirectoryPath;
$SourceItems = Get-ChildItem -recurse $SourceDir;
"Synchronizing Directory Structure..."
foreach ($dir in $SourceItems | ? { $_ -is [IO.DirectoryInfo] }) {
$sourceRelative = $dir.fullname.Substring($SourceDirectoryPath.length + 1);
if ([IO.Directory]::Exists([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative)) -eq $false) {
"Creating folder " + [IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative);
[IO.Directory]::CreateDirectory([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative)) | out-null;
}
}
"Synchronizing Files..."
foreach ($file in $SourceItems | ? { $_ -is [IO.FileInfo] }) {
$sourceRelative = $file.fullname.Substring($SourceDirectoryPath.length + 1);
if ([IO.File]::Exists([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative)) -eq $true) {
CopyFileIfSourceIsLarger ([IO.Path]::Combine($SourceDirectoryPath,$sourceRelative).ToString()) ([IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative).ToString());
} else {
"Creating file " + [IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative);
[IO.File]::Copy([IO.Path]::Combine($SourceDirectoryPath,$sourceRelative).ToString(),[IO.Path]::Combine($DestinationDirectoryPath,$sourceRelative).ToString()) | out-null;
}
}
"All done."
#Thanks to:
#"Identifying Object Types": http://powershell.com/cs/blogs/tobias/archive/2008/10/14/identifying-object-types.aspx
#"Exiting early from foreach": http://stackoverflow.com/questions/10277994/powershell-how-to-exit-from-foreach-object
#"Calling functions with multiple parameters" http://stackoverflow.com/questions/4988226/powershell-multiple-function-parameters
When the script runs, files 1,2,3,5,9, and 10 get copied, and file 6 gets overwritten because it is smaller in the destination.
Here is a batch file that sets up your test case (plus some extra folders to test spaces in the names). I have commented out the two lines that clear out directories A and Z for safety but you can remove the REM statements if you are unconcerned about deleting files in a folder A and Z in the current directory.
#ECHO OFF
REM Uncomment at own risk RD /S /Q A
REM Uncomment at own risk RD /S /Q Z
MD "A\B"
echo aaaaaaaabbbbbbbbcccccccc>"A\B\file 1.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\B\file 2.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\B\file 3.txt"
MD "A\C"
echo aaaaaaaabbbbbbbbcccccccc>"A\C\file 4.txt"
MD "A\D"
echo aaaaaaaabbbbbbbbcccccccc>"A\D\file 5.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\D\file 6.txt"
MD "A\FOLDER E"
echo aaaaaaaabbbbbbbbcccccccc>"A\FOLDER E\file 9.txt"
echo aaaaaaaabbbbbbbbcccccccc>"A\FOLDER E\file 10.txt"
MD "Z\Y"
echo aaaaaaaabbbbbbbbcccccccc>"Z\Y\file 8.txt"
MD "Z\C"
echo aaaaaaaabbbbbbbbccccccccdddddddd>"Z\C\file 4.txt"
MD "Z\D"
echo aaaaaaaa>"Z\D\file 6.txt"