Bonjour,
I'm quite a newbie with ExifTool and I need your help
Although my script works perfectly (although very long) with the iterative call of exiftool.exe, I can't handle the -if statement when I use ExifTool in stay_open mode in a Powershell script.
Indeed, when running in stay_open mode, the final result of the iteration is a list of alerts "Warning: The tag 'if' is not defined" as well as a list of all the files contained in the folder to be processed. The script bypasses the if statement and only deals with the second part of my argument.
This script works well:
Quote
$Source ="J:\pour_archivages\People\072" # test : containing 1,000 files, most with IPTC Category ACE, some not ACE
$Cible = "J:\pour_archivages\News\001" # test : to receive files with IPTC Category not ACE and not SPO
$total_archd = 0
$total_ACE = 0
$ListeFichiers= Get-ChildItem -Path $Source -file
Foreach ($Fichier in $ListeFichiers) {
If (( C:\Users\Administrateur\Documents\mes_scripts\EXIFtool\exiftool.exe -if '$IPTC:Category =~ "/(clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea)/i"' -filename $($File.FullName)) -like "File name*") {
## above, "File name" is part of the string returned when the condition is fulfilled
# move-item -path $Fichier .fullname -Destination $cible
$total_archd ++ # for count testing
}
Else {
$total_ACE ++ # for count testing
}
}
write-host "total des fichiers reclassés dans News : $total_archd"
write-host "total des fichiers ACE dans People : $total_ACE"
(...) #closing procedures
In the stay_open mode, that part goes wrong:
Quote
## NB: to cut short, all the code for creation of ExifTool object and ExifTool process is fine, so I zap it here
Foreach ($File in $ListeFichiers) {
[string]$ArgList ="-if '$IPTC:Category =~ `"/(clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea)/i`"'`n-filename`n$($File.FullName)"
If (($exiftoolproc.StandardInput.WriteLine("$ArgList`n-execute`n")) -like "File name*") {
# move-item -path $File.fullname -Destination $cible -whatif -verbose
$total_archd ++
}
Else {
$total_ACE ++
}
}
write-host "total des fichiers reclassés dans News : $total_archd"
write-host "total des fichiers ACE dans People : $total_ACE"
(...) # closing procedures and display errors and standard output
I think I miss something related to single and double quotes ... or I'm totally wrong in that scripting.
What do you think about?
TLDR;
You need one argument per line. The -if option has an argument that needs to go on a separate line.
- Phil
Thanks Phil!
The script works well now ... however it seems that the condition is still case-sensitive, despite the "i".
Indeed, among the 1000 test files, 80 correspond to the condition but are not detected:
Quote
total files moved to News: 0 (i.e. $total_archd)
total ACE files in People: 1000 (i.e. $total_ACE)
???
Can you paste the exact condition that you used? Are you sure you don't have any extra quotation marks?
- Phil
Your if command should look like this in the arg file
-if
$IPTC:Category =~ /(clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea)/i
While I don't understand powershell script, it seems to me you're overscripting (see Common Mistake #3 (https://exiftool.org/mistakes.html#M3)). Unless there's something else happening, the entire script can be replaced with a single exiftool command:
exiftool.exe -if '$IPTC:Category =~ "/(clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea)/i"' "-Directory=$Cible" $Source
Let exiftool do all the heavy work and parse the exiftool results if you want to display how many files are moved.
Bonsoir,
Sorry for the delay, I was off for a few days.
Phil, I dug the question of quotation marks in Powershell and discovered that I could switch from the argfile to the here-string rule, and the use of backtick character (`)(ASCII 96), which is the PowerShell escape character to prevent the substitution of a variable value in string.
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-6&viewFallbackFrom=powershell-Microsoft.PowerShell.Core (https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-6&viewFallbackFrom=powershell-Microsoft.PowerShell.Core)
So, now my code looks like:
(...)
Foreach ($Fichier in $ListeFichiers) {
## here_string following and backtick to escape $IPTC:Category
$ArgList = @"
-if
`$IPTC:Category =~ /clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea/i
-filename
$($File.FullName)
"@ ## no space allowed before closing "@
## end of here-string
# send exiftool the command to execute
$exiftoolproc.StandardInput.WriteLine("$ArgList`n-execute`n")
}
(...)
It works fine. I get the result in an array that I filter to process the seeked files.
I processed my test-files (1,000) in 1min 13s and found the 80 target-files
So, thanks again Phil!
Quote from: StarGeek on October 11, 2018, 12:32:20 PM
While I don't understand powershell script, it seems to me you're overscripting (see Common Mistake #3 (https://exiftool.org/mistakes.html#M3)). Unless there's something else happening, the entire script can be replaced with a single exiftool command:
exiftool.exe -if '$IPTC:Category =~ "/(clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea)/i"' "-Directory=$Cible" $Source
Let exiftool do all the heavy work and parse the exiftool results if you want to display how many files are moved.
Thanks StarGeek but I've tried that before and it's the reason why I looked for the stay_open feature.
The following code takes
25min 08sec to do the job.
Foreach ($Fichier in $ListeFichiers) {
If (( C:\Users\Administrateur\Documents\mes_scripts\EXIFtool\exiftool.exe -if '$IPTC:Category =~ "/(clj|dis|fin|ebf|edu|env|hth|lab|pol|rel|sci|soc|soi|war|wea)/i"' -filename $($File.FullName)) -like "File name*") {
## above, "File name" is part of the string returned when the condition is fulfilled
# move-item -path $Fichier .fullname -Destination $cible
$total_archd ++ # for count testing
}
Else {
$total_ACE ++ # for count testing
}
}
I think StarGeek's suggestion was to avoid the loop in the script, and call exiftool only once with $Source representing a list of ALL files to be tested (either by specifying a directory name, or a list of file names via the -@ option if you are specifying files individually). This should be at least as fast, and maybe a bit faster, than what you are doing now.
- Phil
Exactly that.
Use the command by itself, replacing $Cible and $Source with the actual directories. As far as I can tell the only thing you're doing is checking the IPTC:Category for a match and moving it. Let exiftool process the source directory (add the -r option (https://exiftool.org/exiftool_pod.html#r-.--recurse) to recurse if necessary) and the command, by itself, should take seconds.
Well done!
ExifTool is just a monstrously awesome tool!
Praised be Phil!
Thx StarGeek!