Here is one solution/approach with bash and find and ed to edit the file in place, but change to something available in your system.
#!/usr/bin/env bash
str='version='
value=1.1
src=../etc/apps/default/data/ui/views
dest=../etc/apps/local/data/ui/views
while IFS= read -rd '' -u3 files; do
IFS= read -r first_line < "$files"
if [[ $first_line = *"$str"* ]]; then
printf 'No change necessary to %s\n' "$files"
else
printf "Copying %s to local %s\n" "$files" "$src/${files##*/}"
cp -v "$files" "$dest" || exit
printf 'Inserting %s at the first line of %s\n' "$str$value" "$dest/${files##*/}"
printf '%s\n' '0a' "<?xml $str${value}?>" . w q | ed -s "$dest/${files##*/}"
fi
done 3< <(find "$src" -type f -name '*.xml' -print0)
Create a dummy directories and files.
mkdir -vp ./etc/apps/default/data/ui/views/
mkdir -vp ./etc/apps/local/data/ui/views/
touch ./etc/apps/default/data/ui/views/{foo,bar,baz,more}.xml
echo 'version="1.1"' > ./etc/apps/default/data/ui/views/foo.xml
Check the created directories and files.
tree ./etc
Output
./etc/
└── apps
├── default
│ └── data
│ └── ui
│ └── views
│ ├── bar.xml
│ ├── baz.xml
│ ├── foo.xml
│ └── more.xml
└── local
└── data
└── ui
└── views
9 directories, 4 files
Check the contents of the files in the default directory.
tail -n+1 ./etc/apps/default/data/ui/views/*.xml
Output
==> ./etc/apps/default/data/ui/views/bar.xml <==
==> ./etc/apps/default/data/ui/views/baz.xml <==
==> ./etc/apps/default/data/ui/views/foo.xml <==
version="1.1"
==> ./etc/apps/default/data/ui/views/more.xml <==
Now execute your script but remove the first . from the path, e.g.
src=./etc/apps/default/data/ui/views
dest=./etc/apps/local/data/ui/views
Output
Copying ./etc/apps/default/data/ui/views/bar.xml to local ./etc/apps/local/data/ui/views/bar.xml
'./etc/apps/default/data/ui/views/bar.xml' -> './etc/apps/local/data/ui/views/bar.xml'
Inserting version="1.1" at the first line of ./etc/apps/local/data/ui/views/bar.xml
Copying ./etc/apps/default/data/ui/views/more.xml to local ./etc/apps/local/data/ui/views/more.xml
'./etc/apps/default/data/ui/views/more.xml' -> './etc/apps/local/data/ui/views/more.xml'
Inserting version="1.1" at the first line of ./etc/apps/local/data/ui/views/more.xml
Copying ./etc/apps/default/data/ui/views/baz.xml to local ./etc/apps/local/data/ui/views/baz.xml
'./etc/apps/default/data/ui/views/baz.xml' -> './etc/apps/local/data/ui/views/baz.xml'
Inserting version="1.1" at the first line of ./etc/apps/local/data/ui/views/baz.xml
No change necessary to ./etc/apps/default/data/ui/views/foo.xml
Check the contents of directories.
tree ./etc
Output
./etc/
└── apps
├── default
│ └── data
│ └── ui
│ └── views
│ ├── bar.xml
│ ├── baz.xml
│ ├── foo.xml
│ └── more.xml
└── local
└── data
└── ui
└── views
├── bar.xml
├── baz.xml
└── more.xml
9 directories, 7 files
Check the file contents from the local directory.
tail -n+1 ./etc/apps/local/data/ui/views/*.xml
Output
==> ./etc/apps/local/data/ui/views/bar.xml <==
<?xml version="1.1"?>
==> ./etc/apps/local/data/ui/views/baz.xml <==
<?xml version="1.1"?>
==> ./etc/apps/local/data/ui/views/more.xml <==
<?xml version="1.1"?>
The script works as intended, just make an adjustment to your needs like Changing the ed code from
printf '%s\n' '0a' "<?xml ${str}?>" . w q | ed -s
to your sed or prefererably an xml editor/parser that can be scripted like xmlstarlet and the likes.
As per the OP's comment including the * glob in the path and an existing file to dest should not be overwritten. The * does not expand on a variable assignment. An array is needed for that.
#!/usr/bin/env bash
shopt -s nullglob
top_dirs=(./etc/apps/*/)
dest=local/data/ui/views/
src=default/data/ui/views/
shopt -u nullglob
str='version='
value=1.1
while IFS= read -rd '' -u3 files; do
IFS= read -r first_line < "$files"
##: skip files if it is in local/data/ui/views/, don't overwrite.
[[ -e "${files/default/local}" ]] && continue
if [[ $first_line = *"$str"* ]]; then
printf 'No change necessary to %s\n' "$files"
elif [[ $first_line != *"$str"* ]]; then
printf "Copying %s to local %s\n" "$files" "${files/default/local}"
cp -v "$files" "${files/default/local}"
printf 'Inserting %s at the first line of %s\n' "$str$value" "${files/default/local}"
printf '%s\n' '0a' "<?xml $str${value}?>" . w q | ed -s "${files/default/local}"
fi
done 3< <(find "${top_dirs[@]/%/"$src"}" -type f -name '*xml' -print0)
The above script was tested against the dummy files/directories with:
mkdir -vp ./etc/apps/dir{1..5}/default/data/ui/views/
mkdir -vp ./etc/apps/dir{1..5}/local/data/ui/views/
touch ./etc/apps/dir{1..5}/default/data/ui/views/{foo,bar,baz,more}.xml
echo 'version=' > ./etc/apps/dir1/default/data/ui/views/foo.xml