Home > Software engineering >  tar `--to-command` : how to send output to a custom function?
tar `--to-command` : how to send output to a custom function?

Time:12-08

I have a very many tar archives I need to extract files from and perform post processing on (amongst other things, changing file encodings and applying some sed commands). I'm interesting in using tar's --to-command option to apply a custom function which does all of those things in sequence.

Up until now, I have been doing:

tar -xzi --to-command=<line of shell commands>

Unfortunately, the list of commands I need to do has got larger and means it is no longer neat (nor probably sensible) to attempt to do everything on one line.

To neaten things up, I've written function in another file, test-function.sh, which (tries to) perform those things in sequence:

#!/bin/bash

post_extract() {
    <the things I need to do>
}

I realise the above is example is incomplete, but my problem at the moment is that I can't get --to-command to find the post_extract function to even go about testing it.

Where should I put post_extract / what would be the idiomatic way of exposing it to tar's --to-command?

CodePudding user response:

Given the behaviors demonstrated in TAR with --to-command, (in particularly, --to-command='md5sum | ...' resulting in md5sum: |: No such file or directory), it's clear that tar --to-command doesn't invoke a shell, but simply performs shell-like parsing and then attempts an execv()-family invocation of the resulting command. This means the target command needs to be something that can actually be executed -- a script, or similar.

This behavior is (loosely) documented in the Running External Commands section of the GNU tar documentation.


One way around this is to have the thing that's invoked be a shell, and then use an exported function to ship code from your parent shell to that child process; as shown below:

#!/usr/bin/env bash
#              ^^^^- MUST be bash, not sh

post_extract() {
  : "do stuff here"
}

export -f post_extract
tar --to-command $'bash -c \'post_extract "$@"\' _' ...
  • Related