What is the simplest code to get the top-level directory part of a makefile variable? Example:

BUILD_DIR = dir/subdir/.../sub-a-dub-dir
        rm -rf <some code which evaluates to "dir" from $(BUILD_DIR)>

PS: I don't mean $(dir $(dir $(BUILD_DIR))), but something which gets the first directory part of any variable value.

  • dirname /tmp/foo/bar will give /tmp or dirname foo/bar/baz will give foo
    – Abhishek A
    Nov 9 '11 at 15:42
  • 1
    @greenmang0: Flagged your answer. First, it's plain wrong (did you even execute those commands?), and second it's for a makefile, not Bash.
    – l0b0
    Nov 9 '11 at 16:18
  • @l0b0 It's a comment, and "it's wrong" isn't a good reason to flag anything, just leave a comment saying what the problem is Nov 9 '11 at 16:23
  • @MichaelMrozek: I flagged it "not constructive / off topic", both of which applies to it.
    – l0b0
    Nov 9 '11 at 19:51
  • I don't understand your question: what do you mean by “the top-level directory part”? Do you mean the part before the first /? Do you guarantee that the argument is a relative path? Are you assuming GNU make? Nov 9 '11 at 23:05

Do you mean the first component of the directory? If so, turn the path into a list of components, then extract the first component. I assume you're using GNU make, and you're not doing something insane like expect file names with whitespace to go through unscathed. Don't try this with an absolute path.

override BUILD_DIR = dir/subdir/.../sub-a-dub-dir
        rm -rf $(firstword $(subst /, ,$(BUILD_DIR)))

I make BUILD_DIR override whatever the user might have passed on the command line, to avoid someone accidentally passing it and having something unintended deleted.

  • BUILD_DIR was supposed to be an internal variable, but you're right, there's still the possibility that someone sets it to something dangerous. So accepting this answer, with the caveat that the solution should not be used :)
    – l0b0
    Feb 17 '12 at 8:39
  • 1
    @l0b0 Since we're assuming GNU make: override BUILD_DIR = … Feb 17 '12 at 8:43

If you're positive that BUILD_DIR will never start with a '/':

rootdir=$( echo $BUILD_DIR | cut -d/ -f1 )

Otherwise, you might need to account for paths that start with '/':

if [[ $BUILD_DIR =~ "^/" ]]; then
        rootdir=$( echo $BUILD_DIR | cut -d/ -f1,2 )
        rootdir=$( echo $BUILD_DIR | cut -d/ -f1 )

echo $rootdir

Or maybe it's best to ignore any path that starts with '/'.

  • 1
    This is for a makefile, not Bash. This is a trivial problem in Bash, but I'm interested in a simple makefile solution.
    – l0b0
    Nov 9 '11 at 16:14
  • One thing you can do in a Makefile is run commands. So you create a shell script, in your path, called rootdir, and in your makefile, run "rm -rf $(rootdir $BUILD_DIR)", or something like that. Or you'll have to do something like pre-define the build root, so that you can rm -rf it later. I would definitely doublecheck the response that the rootdir script can pass back, so you don't end up with a syntax error giving your script rm -rf /. Nov 9 '11 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.