0

when running a command like tar to uncompress a tar file, the files included are displayed on stdout, how do I parse that and capture them in different variables

tar -xvf testfile.tar 
dir/file1.txt 
dir/file2.txt

I want to store file1.txt name in var file1 and file2.txt in var file2.

codeforester
  • 39,467
  • 16
  • 112
  • 140
PMat
  • 2,039
  • 2
  • 29
  • 46
  • 3
    Redirect the output using *process substitution* or *command substitution* and capture it in an *indexed array*? (e.g. `array=( $(tar -tvf testfile.tar) )` )? – David C. Rankin May 18 '17 at 19:31
  • cool..that works – PMat May 18 '17 at 20:04
  • @DavidC.Rankin: AFAIK, `process substitution` is not a `POSIX` shell feature, quoting this only because of `sh` tag in the question – Inian May 19 '17 at 15:51
  • i don't have bash support, array=$(tar -xvf testfile.tar) and reading in a loop – PMat May 19 '17 at 16:46
  • Then you are basically going to need to use a *pipe* or a *tmp file*, e.g. `tar -tvf testfile.tar | while IFS=$'\n' read -r fname; do printf "found: %s\n" "$fname"; done` or redirect the output `tar -tvf testfile. tar > tmpfile && while IFS=$'\n' read -r fname; do printf "found: %s\n" "$fname"; done – David C. Rankin May 19 '17 at 16:57
  • @Inian good tag catch. – David C. Rankin May 19 '17 at 16:59
  • @DavidC.Rankin: Another one ;) `$'..'` ANSI C-style quoting is also `bash` specific – Inian May 19 '17 at 17:09
  • This really isn't something you want to do in POSIX `sh`. Pick a different language. And if you are picking a new language, use one (like Python) that has a proper library for examining tar files. – chepner May 19 '17 at 20:05
  • array=$(tar -xvf testfile.tar) and reading in a loop. It works for me – PMat May 19 '17 at 22:54
  • Both @DavidC.Rankin and Mike, have similar answer. Since David posted it first, if you can post the answer, i can accept it – PMat May 19 '17 at 23:00

2 Answers2

0

here's one way to do it

count=1
for i in $(tar -tzf testfile.tar); do eval "file${count}=$i"; count=$((count+1)); done

it will give you something like this:

file1=dir/
file2=dir/file2.txt
file3=dir/file1.txt

in my example, i created a dir folder which technically isn't the in yours hence the 1st line dir/

Mike
  • 89
  • 4
  • that works too, but the first one will not be dirname, tar does not echo dir name – PMat May 18 '17 at 20:05
  • I just wanted to clarify for general knowledge that i tared my folder with file1 and file 2 in it hence why it was there in my output. – Mike May 18 '17 at 20:30
0

With your question tagged shell unix sh, your question requests an answer that is POSIX shell compliant, but your response within the comments indicates you are working in bash (or some other shell that supports arrays). Depending upon your shell, tagging makes a difference in the answers you will receive and what will (or won't) work for you. (as @Inian correctly points out)

If you are working in a shell that supports arrays (bash, ksh, zsh, etc), the easiest way to capture the output of the tar -xvf testfile.txt command is by using command substitution to fill an array, e.g.

array=( $(tar -tvf testfile.tar) )

In the event you need a POSIX shell solution (Bourne shell, dash, etc) then you will either need to pipe the output from tar to read or redirect its output to a temporary file and read the output from there. You can use something similar to the following,

tar -tvf testfile.tar | while IFS="\n" read -r fname
do
    printf "found: %s\n" "$fname"
done

Or if you would like to use a temporary file, then something like the following:

tar -tvf testfile.tar > tempfile.txt
while IFS="\n" read -r fname
do
    printf "found: %s\n" "$fname"
done <"tempfile.txt"
rm tempfile.txt

note: depending on your OS and implementation of read, you may or may not have the -r option available. Simply omit if your implementation does not provide it.

Glad you were able to get this sorted out. If you have any further questions, please let us know.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • You cannot safely create an array with an unquoted command substitution. `IFS="\n"` splits the input on `n`, not a newline. You actually want `IFS=`, so that *no* word-splitting is performed on the single line that `read` takes from the input. – chepner May 22 '17 at 13:55
  • Where do you see `IFS` set for an array? There is NO discussion regarding `IFS` and the array. `IFS` is only discussed as it relates to the POSIX `read`. Please do not invent words to justify a downvote. Please note the **In the event you need a POSIX shell solution** beginning the 3rd full paragraph. Thanks. – David C. Rankin May 22 '17 at 13:59
  • `IFS` is a separate issue, and still wrong even for the POSIX solution. `array=( $(tar ...) )` will not work if any of the file names contain whitespace; the components will be treated as separate elements of the array. – chepner May 22 '17 at 14:00
  • I agree with that. But that was not part of the answer. A simple *helpful* comment noting that to prevent word splitting `IFS=` can be included before the *process substitution* will suffice. If we are all going to *nit-pick* each others answers -- this is really not going to continue to be the helpful site it has been. – David C. Rankin May 22 '17 at 14:01