0

I have to find recursively inside a bash script. Since I can invoke the bash script from anywhere, I am forced to use the absolute path. Sometimes the absolute path can get very long, and the output get's tedious in the following:

#!/usr/bin/env bash
find /long/absolute/path -type f | sort

So I did:

#!/usr/bin/env bash
find /long/absolute/path -type f | xargs -L 1 -I @ echo $(basename @) | sort

But this doesn't gives the basename. Could you please find out where I am going wrong?

2 Answers 2

2

You went wrong in two ways:

  1. You're passing semi-arbitrary filenames from find through two pipes -- to xargs and then on to sort. Use null-terminated -print0 from find, if you're able, or embed the actions inside -exec, as maulinglawns demonstrated.

  2. IF you had filenames that never contained any characters from $IFS, your command would still fail because you've asked xargs to execute echo with a command substitution; that command substitution asks basename to output the base name of @, which probably doesn't exist. Closer would have been:

    find /long/absolute/path -type f | xargs -L 1 -I @ basename @ | sort
    

... as that would have allowed xargs to interpolate the filenames as arguments to basename.

2
  • Thanks for the answer. Why do you suggest that probably @ didn't exists? The above script file in the question does print out the filenames although with the absolute path, implying that @ is not blank
    – Porcupine
    Commented Sep 17, 2018 at 19:15
  • 2
    when you used command substitution, it ran before xargs filled in @, so basename was looking for a file named exactly @
    – Jeff Schaller
    Commented Sep 17, 2018 at 19:24
1

This works for me:

find /some/long/path/ -type f -exec basename {} \;| sort
3
  • This works. Is \; necessary? Any idea why mine didn't work?
    – Porcupine
    Commented Sep 17, 2018 at 18:46
  • 1
    Yes, it is necessary. Without it you get find: missing argument to '-exec'. I don't know why your variant didn't work, I rarely use xargs myself.
    – anon
    Commented Sep 17, 2018 at 18:48
  • 1
    be aware of arbitrary filenames being passed from find through the pipe to sort --- touch $'/some/long/path/foo\nbar' ---> bar on one line, foo on the next.
    – Jeff Schaller
    Commented Sep 17, 2018 at 18:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .