I have a directory with header and payload xml files named like(no .xml extension is there):
File1
File1_PAYLOAD
File2
File2_PAYLOAD
I need to check whether the header file contains two attributes which if present the file should be moved to another directory along with its PAYLOAD file. I'm using xmllint --xpath to check the attributes, it has a headers tag inside which are a bunch of header tags, my query:
xmllint --xpath "boolean(//*[local-name()='headers' and *[local-name()='header'][@name='Type' and @value='AAAA'] and *[local-name()='header'][@name='Update' and @value='DONE']])
The xpath query works fine and returns a true/false according to whether the attributes are present or not. Problem comes with how to iterate over only header files and move them. I've tried to use find like:
#!/bin/bash
dest="/tmp/proc"
loc="/tmp/files"
find $loc -maxdepth 1 -mindepth 1 ! -name '*_PAYLOAD' -exec xmllint --xpath "boolean(//*[local-name()='headers' and *[local-name()='header'][@name='Type' and @value='AAAA'] and *[local-name()='header'][@name='Update' and @value='DONE']]) " {} \; -exec mv {} $dest \; -exec mv {}_PAYLOAD $dest \;
But this query moves the files even when my xpath query return false, I think maybe find -exec is taking the true/false returned as an string hence true and still proceed to the next exec. So I tried find with sh -c, so that I can incorporate some sort of if and else structure:
#!/bin/bash
dest="/tmp/proc"
loc="/tmp/files"
find $loc -maxdepth 1 -mindepth 1 ! -name '*_PAYLOAD' -exec sh -c '
for file do
stat=$(xmllint --xpath "boolean(//*[local-name()='headers' and *[local-name()='header'][@name='Type' and @value='AAAA'] and *[local-name()='header'][@name='Update' and @value='DONE']]) " "$file" | grep 'true' | wc -l)
if [ "$stat" -eq 1 ]
mv "$file" "$dest"
mv "$file"_PAYLOAD "$dest"
done' sh {} \;
but this gives an error :
sh: -c: line 6: syntax error near unexpected token `done' sh: -c: line 6: `done'
This syntax I saw from https://unix.stackexchange.com/questions/321697/why-is-looping-over-finds-output-bad-practice/321753#321753
Maybe you can try below, please check if this works for you:
#!/bin/bash
dest="/tmp/proc"
loc="/tmp/files"
for i in $(find "$loc" -maxdepth 1 -mindepth 1 ! -name "*_PAYLOAD" -exec basename "{}" \;)
do
stat=$(xmllint --xpath "boolean(//*[local-name()='headers' and *[local-name()='header'][@name='Type' and @value='AAAA'] and *[local-name()='header'][@name='Update' and @value='DONE']]) "$i"
if [[ "$stat" == "true" ]]
then
mv "$i" "$dest"
mv "$i"_PAYLOAD "$dest"
fi
done