Skip to content

Instantly share code, notes, and snippets.

@molomby
Last active March 27, 2019 06:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save molomby/1d66738490498548e5d042066299510a to your computer and use it in GitHub Desktop.
Save molomby/1d66738490498548e5d042066299510a to your computer and use it in GitHub Desktop.
Docs for appending the parent directory name to the name of files it contains

Create some test files. I've assumed your filenames have a single "." character:

mkdir foo
touch foo/one.txt foo/two.txt foo/three.txt

If you list the files (ll foo) you'll get something like:

total 0
-rw-r--r--  1 molomby  staff     0B 21 Mar 21:49 one.txt
-rw-r--r--  1 molomby  staff     0B 21 Mar 21:49 three.txt
-rw-r--r--  1 molomby  staff     0B 21 Mar 21:49 two.txt

Now we're going to loop over the files and use some string manipulation to rename them.

for file in foo/*;
do 
  mv "${file}" "${file%%.*}-${file%%/*}.${file##*.}"
done

Lets unpack that a little.

  • The first line itterates over the files matching the foo/* glob. The file var will have a values like foo/one.txt, etc.
  • We're running a move command from the current file (${file}) to a new filename built out of parts:
    • ${file%%.*} -> the file path, with everything after the "." removed (eg. foo/one)
    • - -> a litteral "-" charactor
    • ${file%%/*} -> the file path, with everything after the "/" removed (eg. foo)
    • . -> a litteral "." charactor
    • ${file##*.} -> the file path, with everything before the "." removed (eg. txt)

The commands are wrapped in quotes in case there are spaces in the filenames. So we end up running these commands:

mv "foo/one.txt" "foo/one-foo.txt"
mv "foo/three.txt" "foo/three-foo.txt"
mv "foo/two.txt" "foo/two-foo.txt"

If you listing the files again (ll foo) you'll get:

total 0
-rw-r--r--  1 molomby  staff     0B 21 Mar 21:49 one-foo.txt
-rw-r--r--  1 molomby  staff     0B 21 Mar 21:49 three-foo.txt
-rw-r--r--  1 molomby  staff     0B 21 Mar 21:49 two-foo.txt
@marilenad
Copy link

Why does

for folder in test_dir/C*
do 
for file in ${folder}/*;
do 
  mv "${file}" "${file%%.*}-${folder##*/}.${file##*.}"
done
done

work

but not

for folder in test_dir/C*
do 
for file in ${folder}/*;
do 
  mv "${file}" "$${folder##*/}-{file%%.*}.${file##*.}"
done
done

It's to do with the string but I don't understand how to stop the manipulation going up so far?

@marilenad
Copy link

Neverrrrr miiiind! I worked out an ugly solution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment