0

I have the follwing which creates a directory from a list of files:

for file in $(ls *.txt); do 
    folder=${file//.txt/ }; 
    folder=${folder//./'/'}; 
    folder=${folder//[[:space:]]/}; 
    mkdir -p $folder;
done

Can I link the 3 string manipulation commands that assign folder into one line?

I've tried several things with no success. Is it possible to use the | operator somehow?

turnip
  • 2,246
  • 5
  • 30
  • 58
  • 2
    No; you cannot chain parameter expansion operators within a single expansion. – chepner Jul 02 '18 at 15:23
  • agreed with above. And why do you care? If you're looking to reduce line count, then just join those assignments onto one line, i.e. `folder=..; folder=... ; folder-..`. You could probably put all of those manipulations into one `sed` command, but then you'd be creating a subprocess to execute it, and this will be slower and more inefficient than using the shell's built in paramter expansions. Good luck. – shellter Jul 02 '18 at 16:17
  • 1
    Unrelated hint: Replace `for file in $(ls *.txt)` with `for file in *.txt`. It's shorter and much safer. – Socowi Jul 02 '18 at 16:41
  • If you really wanted, you could use `folder="$(sed 's,\.txt, ,g;s,\.,/,g;s,[[:space:]],,g' <<< "$file")"`, but there is no benefit. – Socowi Jul 02 '18 at 16:50

1 Answers1

1

Bash cannot do this, but Z Shell (zsh) (which is very similar) can nest the replacements:

for file in *.txt; do
    folder=${${${file//.txt/ }//./'/'}//[[:space:]]/}; 
    mkdir -p $folder;
done

(You don't need to do $(ls *.txt) (parsing ls in this way is dangerous: you lose all spaces) since you can just give it *.txt, which properly handles spaces in filenames. This works in any POSIX shell.)

Adam Katz
  • 14,455
  • 5
  • 68
  • 83