SkrillKill
SkrillKill

Reputation: 81

Error handling in batch files

I'm working on a script to automate a couple tasks. Essentially, it just renames files if they exist. However, these files are critical to the operation of some other software. If renaming a file fails, or if it cannot find file, i would like it to say which file it was. However, the REN command isn't very descriptive when it fails. I know that if it fails, it raises ERRORLEVEL to 1. Is there any other information i can get from the failure, like the file name? Or is it pretty much just a success or fail?

Machines this will be running on are Windows 7 and up, so powershell is also an option if necessary but i would prefer batch.

Thanks

Upvotes: 2

Views: 2778

Answers (2)

Stephan
Stephan

Reputation: 56228

as already noted, ren working with wildcards don't tell you which file failed. So you have to process each file individually. Thanksfully, there are commands for doing so: for and forfiles.

for %%a in (*) do ren "%%a" "destination.ext" 2>nul || echo FAILED: %%a

this tries to rename every file to "destination.ext", which works fine for the very first of them.
Renaming the rest of the files will fail (destination already existing).
|| is a "if previous command failed, then" operator.
2>nul removes the errormessage (useless for you, as it doesn't tell you the filename)

(Note: this is syntax for batchfiles. If you try it directly on command line,
replace each %%a with %a)

Upvotes: 1

mklement0
mklement0

Reputation: 440297

As Ken White points out in a comment on the question, the error messages emitted by cmd.exe's ren command do not include the filename(s) involved.

PowerShell, by contrast, provides verbose error messages that do include filenames.
Take the following sample script:

# Create helper sample files.
$tempFiles = "$env:TEMP\foo", "$env:TEMP\bar"
$null = New-Item -Type File $tempFiles

# Try to rename a nonexistent item.
Rename-Item \no\such -NewName foo

# Try to rename to a file that already exists.
Rename-Item $env:TEMP\foo -NewName bar

# Clean up the sample files.
Remove-Item $tempFiles

If you save the above to a *.ps1 file and run it (assuming you have permitted scripts to run), you'll see the following error output:

Rename-Item : Cannot rename because item at '\no\such' does not exist.
At C:\Users\jdoe\Desktop\pg\pg.ps1:8 char:5
+     Rename-Item \no\such -NewName foo
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand

Rename-Item : Cannot create a file when that file already exists.
At C:\Users\jdoe\Desktop\pg\pg.ps1:11 char:5
+     Rename-Item $env:TEMP\foo -NewName bar
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (C:\Users\jdoe\AppData\Local\Temp\foo:String) [Rename-Item], IOException
    + FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand

While the output is verbose, it does contain all relevant information, and you can even inspect it programmatically, via the automatic $Error variable, which contains all errors that were reported in the session in reverse chronological order ($Error[0] contains the most recent error).

Not that, by default, the PowerShell script will continue to run when these errors happen, because they are considered non-terminating.

  • The simplest way to cause the script to abort right away is to start your script with line $ErrorActionPreference= 'Stop'.

  • Alternatively, you can use -ErrorAction Stop on a per-command basis.

Run Get-Help about_Preference_Variables and Get-Help about_CommonParameters to learn more.

Upvotes: 3

Related Questions