I am trying to delete a folder using robocopy mirroring like this:
Start-Process -FilePath "robocopy.exe" -ArgumentList "$emptyDir $sourcePath /mir /e /np /ns /nc /njs /njh /nfl /ndl" -Wait -PassThru -NoNewWindow but still get a line of output for every deleted file
I tried adding >nul 2>&1 as explained in another answer here Start-Process -FilePath "robocopy.exe" -ArgumentList "$emptyDir $sourcePath /mir /e /np /ns /nc /njs /njh /nfl /ndl >nul 2>&1" -Wait -PassThru -NoNewWindow but still get the same output.
Since you're running robocopy in the current console window (-NoNewWindow), synchronously (-Wait), there is no reason to use Start-Process at all - just invoke robocopy directly, which also allows you to use > redirections effectively:
robocopy.exe $emptyDir $sourcePath /mir /e /np /ns /nc /njs /njh /nfl /ndl *>$null
Note:
Direct execution makes a program's stdout and stderr output directly available to PowerShell, via its success and error output streams.
*>$null is a convenient PowerShell shortcut for silencing all output streams - see about_Redirection.
Another benefit of direct invocation is that the external program's process exit code is reported in PowerShell's automatic $LASTEXITCODE variable.
See also:
This answer provides background information.
GitHub docs issue #6239 provides guidance on when use of Start-Process is and isn't appropriate.
As for what you tried:
You fundamentally cannot suppress output from a process launched with Start-Process -NoNewWindow on the PowerShell side.
Trying to silence command output at the source, i.e. as part of the target process' command line with >nul 2>&1, would only work if cmd.exe were the -FilePath argument and you passed a robocopy command to it. > redirections are a shell feature, and robocopy itself isn't a shell.
You can try to pass arguments via splatting, and then use the object pipeline to parse line by line.
In the example below, I'm going to split the arguments into two groups, in case you wanted to change out the options programmatically.
$roboFileArgs = #(
<#
If you're sure your argument is already a string or
a primitive type, there's no need to quote it.
#>
$emptyDir
$sourcePath
)
$roboFlags = "/mir","/e","/np","/ns","/nc","/njs","/njh","/nfl","/ndl"
# We can use splatting to pass both lists of arguments
robocopy.exe #roboFileArgs #roboFlags |
Foreach-Object {
<#
process output line by line and turn it into objects
or pipe to Out-Null if you truly don't care.
#>
}
Related
I have a PowerShell script that gets usernames from a .CSV file and uses the username to robocopy that users data from our old server to the new one. The usernames are formatted as "firstname.lastname" within the organisation. I need the log files for each users robocopy to output as "firstname.lastname-dd-MM-HH:mm.txt"
However when I run my PowerShell script that gets the username from CSV, everything after the firstname becomes the file extension, despite PowerShell showing that it was logged as a .txt.
The script:
$users = Get-Content C:\Veritech\RoboCopy\Users\UserTest.csv
$dt = get-date -f dd-MM-HH:mm
foreach ($UserName in $users) {
robocopy "\\*****\profile$\$UserName" "E:\Shares\Profile$\$UserName" /E /COPYALL /ZB /TEE /R:3 /W:5 /L /NS /NJS /NJH /NDL /FP /log+:"C:\*****\RoboCopy\Users\P-$UserName-$dt.txt"
}
PowerShell log, when run manually, not via task scheduler or .ps1 as intended:
I'm looking for a command using cmd.exe (Win 10) that will list all files in a folder and its sub-folders, alphabetically, irrespective of the paths, and that will show the filenames only (no paths).
The commands that I'm familiar with (including, for example, "dir ..\samplefolder /b /s /A-D /o:n > filelist.txt") all include the paths in the output, and so are not what I'm looking for.
Thank you.
(for /r "c:\startfolder" %%A in (*) do echo %%~nxA)|sort
(this is batch file syntax; for use directly on the command line, replace every %% with just %)
for /r loops recursively over all (non-hidden) files.
%%~nxA shows name and extension only (if you want just the name without extension, use %%~nA)
See for /? for more information on those modifiers.
If the machine is on the current PowerShell 5 or higher, you could use:
(Get-ChildItem -Recurse -File -Path '..\samplefolder').Name |
Sort-Object |
Out-File -PSPath 'filelist.txt' -Encoding ascii
In a .bat file script.
>"filelist.txt" powershell -NoLogo -NoProfile -Command ^
"(Get-ChildItem -Recurse -File -Path '..\samplefolder').Name | Sort-Object"
If the machine does not have a current PowerShell, it should be upgraded or use:
>"filelist.txt" powershell -NoLogo -NoProfile -Command ^
"(Get-ChildItem -Recurse -Path '..\samplefolder'|" ^
"Where-Object { -not $_.IsContainer}).Name |" ^
"Sort-Object"
Trying to use Powershell to backup some large dir -newbie
I can't make this line to work
"C:\Robocopy\RoboCopy.exe" $source $destination "/E /R:10 /W:5 /V /ETA"
Robocopy at best (depending on the " i put here or there..) is executed but it's its GUI that is launched (and nothing more is done).
There's no issue with the $dest and $source (I manage to log into a txt file and his is working)
Thank you
Use this:
& "C:\Robocopy\RoboCopy.exe" $source $destination /E /R:10 /W:5 /V /ETA
The & (call) operator is required if you want PowerShell to run a quoted string as a command.
In this specific case, the quotes are not needed because the executable's path and filename don't contain spaces, so you can just write this instead:
C:\Robocopy\RoboCopy.exe $source $destination /E /R:10 /W:5 /V /ETA
But is robocopy.exe really sitting in C:\Robocopy? Do you have that directory name? Robocopy.exe is a tool that comes with the OS and should already be in the path. Why not just this?
robocopy $source $destination /E /R:10 /W:5 /V /ETA
I am using Robocopy to write to log files:
robocopy "C:\source" "E:\destination" /e /l /njs /njh /log:C:\folder1\reconcile1.txt
When I use this in my batch file the console shows: Log File : C:\folder1\reconsile1.txt
I do no want anything echoed from this command. Is there a way to keep this away from appearing on the console?
You could redirect all output to nul:
robocopy "C:\source" "E:\destination" /e /l /njs /njh /log:C:\folder1\reconcile1.txt > nul
I'm using an older version of robocopy that includes percentages in the log even if the /NJH and /NJS paramters are set. So I'd like to remove the percentages from the log:
72880735 H:\1.txt
100%
33038490 H:\10.txt
100%
64878348 H:\2.txt
100%
25875810 H:\3.txt
0%
100%
I've tried with
(Get-Content $logfile) | Where-Object {
$_ -match '[\s](\d{1,})(\s+)(\w\W\W.+)'
} | Set-Content $logfile
But that results in
72880735 H:\1.txt
33038490 H:\10.txt
64878348 H:\2.txt
25875810 H:\3.txt
0%
So I get the 100%'s stripped out, but not the 0%.
/njh and /njs have nothing to do with the percentage information. You need to suppress progress output by adding the option /np to your robocopy commandline.
From the documentation:
/np Specifies that the progress of the copying operation (the number of files or directories copied so far) will not be displayed.
Edit: After taking a look at your actual commandline it looks like /np is not compatible with /mt. Adding the latter parameter makes robocopy display progress output even if /np is present. If you don't require running multi-threaded I'd remove that parameter (add /ndl to prevent directories from appearing in the output).
I would also recommend using splatting instead of putting the parameter list into a single string:
$params = $src, $dest, ('/LOG:"{0}"' -f $logpath), '/L', '/NP', '/NC', '/BYTES',
'/NJH', '/NJS', '/NDL', '/E', '/MOVE', '/XC', '/XN', '/XO', '/XD',
$excludedFoldersList
& robocopy #params
If for some reason you must use multi-threading you should be able to remove progress information from the log after completion like this:
(Get-Content $logpath) | Where-Object {
$_ -notmatch '^\s*\d{1,3}%\s*$'
} | Set-Content $logpath