Search code examples
xargs

how do I concatenate '/' to words read from input with xargs before passing them as arguments to a command?


I have saved a list of file paths to a text file and unfortunately the leading '/' gets dropped in the process from each path turning the file path from an absolute to a relative one. I am using <files.txt xargs -d'\n' touch to touch all the file in the list. How can I concatenate a leading '/' to each path while reading the words (paths) before passing them as arguments to the touch command?

I tried using echo '/' and it hasnt worked


Solution

    1. Simple way, if it's okay to run a separate touch for each file -- this is less efficient, but probably not enough to matter unless you have a huge number of files:

      <files.txt xargs -I{} touch /{}
      
    2. More complicated but efficient, if you have a shell that does arrays (ksh bash zsh):

      <files.txt xargs -d'\n' bash -c 'for f do a+=("/$f"); done; touch "${a[@]}"' argv0
      # BUT this might fail in an edge case where the list of names without /
      # fits in ARG_MAX but the modified list with / added does not
      
    3. Change the input instead, simple and efficient for huge number of files, and safe:

      <files.txt sed 's:^:/:' | xargs -d'\n' touch
      
    4. Don't need xargs if the number of files is NOT huge:

      ( set -f; IFS='\n'; touch $(<files.txt sed 's:^:/:') )
      # the outer parens can be omitted in a script that will exit 
      # without/before needing the -f and IFS settings restored
      
    5. Don't even need touch, just the shell:

      while read -r f; do : >>"/$f"; done <files.txt