find . -iname '*.zip' -exec bash -c 'name=$(unzip -qql "$1" '*_IPC.csv' | grep -oE '[[:digit:]]{8}_IPC.csv' | head -n1); [ "$name" ] && mv "$1" "${name%csv}zip"' none {} ';'
How it works
This command has the form:
find . -iname '*.zip' -exec bash -c '...' none {} ';'
This searches for .zip file in the current directory and all subdirectories under it. For each such file found the bash command in single quotes is executed. The name of the file found is supplied at argument one, $1
, to the bash command. In our case, the bash command has two parts. The first extracts the csv file name and saves it in bash variable name
:
name=$(unzip -qql "$1" '*_IPC.csv' | grep -oE '[[:digit:]]{8}_IPC.csv' | head -n1)
The above uses command substitution: the command inside $(...)
is run and its standard out is captured. In this case, we assign it to the variable name
. The command unzip -qql "$1" '*_IPC.csv'
quietly extracts all file names from the zip file that match the glob *_IPC.csv
. We don't need to limit to the glob *_IPC.csv
but, if the zip file has many files in it, this may speed things up.
The grep command, rep -oE '[[:digit:]]{8}_IPC.csv'
further selects only those name that start with 8 digits. The head -n1
command selects the first such name found. If there was only one such name, head -n1
wouldn't be needed. But, keeping head
could speed things up because it causes the pipeline to terminate after the first match.
The second part tests that we succeeded in getting a non-empty name
and, if so, renames the zip file:
[ "$name" ] && mv "$1" "${name%csv}zip"
The above uses suffix removal to change the csv file name to a zip file name. ${name%csv}
returns $name
after having removed the suffix csv
. ${name%csv}zip
adds a zip suffix.