Technical details: Ubuntu 20.04 or so, writing a bash script.
I am writing a script that receives a larger number of tar.gz files, unzips them, and copies their components into temporary directories, one per tar.gz file. Let's call the individual directories tempN, where N is the number of the directory. So far that works just fine, no problem.
Now, in those tar files one of two things will be true:
- The user who created them wrapped their stuff up into one more level of directory, so now there is a directory tempN/someUserDirectory. I do not know the name of someUserDirectory since it depends on what the user felt like naming it. I do know for sure that there are no subdirectories in that user directory, so the files I need from the user live entirely in that directory (and not in tempN if the user chose to create a subdirectory)
- The user did NOT create the subdirectory, so their files are in the tempN directory itself
In case 1, I need to transfer the files from tempN/someUserDirectory into tempN itself so I can process the user files. But since I don't know the name of someUserDirectory, how do I do that? Is there like an opposite of .. that gets me one layer deeper?
1 Answer 1
After extraction, count the number of items in the output directory:
declare -a items=("$outdir"/*)
(You probably can assume that your users won't give you .dotfiles, I guess?)
If there's just one item, and it's a directory,
if (( ${items[@]} == 1 )) && [[ -d "${items[0]}" ]]
then just add its name to the output path before continuing to work on $outdir:
outdir=${items[0]}
Another approach would be to list all files in the archive and check whether they all have the same 1st path component, and if so use tar's option to strip components when extracting. However, listing files in a .tar archive can be nearly as slow as extracting it, so this method is more suitable for .zip/.rar archives (which have a central file index).