I have a folder with sub-folders as below (for the sake of the question, I have simplified)
I am able to find the folders where check.lock
files are present using
find . -type f -name "check.lock"
and find the folders where local.lock
files are present using
find . -type f -name "local.lock"
As you can see variant2 is folders binary_test
and component_test
do NOT have the local.lock
files (but they have the check.lock
files).
How can I find the these (do not have to the variant names, the whole paths are sufficient). In other words, the output of find . -type f -name "check.lock"
will be 9 lines & the output of find . -type f -name "local.lock"
will be 6 lines & I want those 3 lines where the "local.lock" was not found.
so I want to take the output of find . -type f -name "check.lock"
and then compare that with find . -type f -name "local.lock"
and do a grep
(with unit_test
/variant1
or something like that) so that I get a smaller list to visually compare.
I tried { find . -type f -name "check.lock" && find . -type f -name "local.log"; } | grep "unit_test"
but the output is strange (shows only one line with "check.lock"`
Any helpy is appreciated. If you can at least let me know how to pass out of 2 commands into grep, that would also help.
├── src
│ ├── unit_test
│ │ ├── variant1
│ │ │ ├── check.lock
│ │ ├── variant2
│ │ │ ├── check.lock
│ │ ├── variant3
│ │ │ ├── check.lock
│ ├── binary_test
│ │ ├── variant1
│ │ │ ├── check.lock
│ │ ├── variant2
│ │ │ ├── check.lock
│ │ ├── variant3
│ │ │ ├── check.lock
│ ├── component_test
│ │ ├── variant1
│ │ │ ├── check.lock
│ │ ├── variant2
│ │ │ ├── check.lock
│ │ ├── variant3
│ │ │ ├── check.lock
├── public
│ ├── unit_test
│ │ ├── variant1
│ │ │ ├── local.lock
│ │ ├── variant2
│ │ │ ├── local.lock
│ │ ├── variant3
│ │ │ ├── local.lock
│ ├── binary_test
│ │ ├── variant1
│ │ │ ├── local.lock
│ │ ├── variant2
│ │ ├── variant3
│ │ │ ├── local.lock
│ ├── component_test
│ │ ├── variant1
│ │ │ ├── local.lock
│ │ ├── variant2
│ │ ├── variant3
│ │ │ ├── local.lock
diff -y
:diff -y <( cd src && find * -type f -name check.lock -printf %h\\n | sort
) <( cd public && find * -type f -name local.lock -printf %h\\n | sort )
binary_test/variant1 binary_test/variant1
binary_test/variant2 <
binary_test/variant3 binary_test/variant3
component_test/variant1 component_test/variant1
component_test/variant2 <
component_test/variant3 component_test/variant3
unit_test/variant1 unit_test/variant1
unit_test/variant2 unit_test/variant2
unit_test/variant3 unit_test/variant3
mkdir public/component_test/variantZ
touch public/component_test/variantZ/local.lock
diff -y <( cd src && find * -type f -name check.lock -printf %h\\n | sort
) <( cd public && find * -type f -name local.lock -printf %h\\n | sort )
binary_test/variant1 binary_test/variant1
binary_test/variant2 <
binary_test/variant3 binary_test/variant3
component_test/variant1 component_test/variant1
component_test/variant2 <
component_test/variant3 component_test/variant3
> component_test/variantZ
unit_test/variant1 unit_test/variant1
unit_test/variant2 unit_test/variant2
unit_test/variant3 unit_test/variant3
sed
This whill show both directories side by side, with symbol <
or >
when some file seem missing:
diff -y <(
cd src &&
find * -type f -name "check.lock" |
sort |
sed 's/check.lock/local.lock/'
) <(
cd public &&
find * -type f -name "local.lock" |
sort
) |
sed 's/^\([^[:space:]]*\)local.lock/\1check.lock/'
binary_test/variant1/check.lock binary_test/variant1/local.lock
binary_test/variant2/check.lock <
binary_test/variant3/check.lock binary_test/variant3/local.lock
component_test/variant1/check.lock component_test/variant1/local.lock
component_test/variant2/check.lock <
component_test/variant3/check.lock component_test/variant3/local.lock
> component_test/variantZ/local.lock
unit_test/variant1/check.lock unit_test/variant1/local.lock
unit_test/variant2/check.lock unit_test/variant2/local.lock
unit_test/variant3/check.lock unit_test/variant3/local.lock
Where 1st column show src
and 2nd show public
.
Final sed
command will replace local.lock
by check.lock
only if present before any space
.
diff <(
cd src &&
find * -type f -name "check.lock" |
sort |
sed 's/check.lock/local.lock/'
) <(
cd public &&
find * -type f -name "local.lock" |
sort
) |
sed '/^[<>]/!d;s/^/Missing in /;s/</public:/;
/>/{s/>/src:/;s/local.lock/check.lock/;};'
Missing in public: binary_test/variant2/local.lock
Missing in public: component_test/variant2/local.lock
Missing in src: component_test/variantZ/check.lock
find | sed | sh
By using syntax sed < <(...)
, I will confine cd
in a subshell, which won't affect current environment.
sed < <(
cd src &&
find * -type f -name "check.lock"
) -e 's/\(.*\)check.lock/test -f \1local.lock || \
echo public\/\1local.lock missing/;
1icd public
' | sh
public/binary_test/variant2/local.lock missing
public/component_test/variant2/local.lock missing
bash
:Using rare option -c
and -C
with mapfile
command.
existInPublic() {
[[ -e public/${2/check/local} ]] || echo "public/${2/check/local} missing."
}
shopt -s globstar
mapfile -tc1 -CexistInPublic _ < <(cd src && printf %s\\n **/check.lock)
public/binary_test/variant2/local.lock missing.
public/component_test/variant2/local.lock missing.
bash
and without loop:In fact there is a loop of only 2 cycles: for grp in src public
, but no loop over list of files. This could render quickly even on big trees.
diffSrcPublic() {
local grp varnam fstr grp2
local -i idx=1 uShoptGlobstar=0
local -Ai diffList='()'
if ! shopt -q globstar; then uShoptGlobstar=1;shopt -s globstar; fi
for grp in src public; do
varnam=($grp/**/*.lock)
varnam=(${varnam[@]#$grp/})
varnam=(${varnam[@]%/*.lock})
printf -v fstr 'diffList["%%s"]+=%d\\n' $((idx))
idx=$(( idx << 1 ))
. <(printf "$fstr" "${varnam[@]}")
done
printf -v fstr '%s:%%s ' "${diffList[@]}"
printf -v fstr "$fstr" "${!diffList[@]}"
read -a grp <<< "$fstr"
grp=(${grp[@]/%3:*})
grp2=(${grp[@]/%2:*})
grp=(${grp[@]/%1:*})
printf 'Missing in src: %s\n' ${grp[@]#2:}
printf 'Missing in public: %s\n' ${grp2[@]#1:}
(( uShoptGlobstar )) && shopt -u globstar
}
diffSrcPublic
Missing in src: component_test/variantZ
Missing in public: component_test/variant2
Missing in public: binary_test/variant2