How to edit text in a string with sed

Say you’ve got a bunch of files to organize from something like mypic20190327.jpg to 2019/03/mypic20190327.jpg. sed is a nifty tool to help you with that. You’ll need to use regex to match each part, then reference each matched part in the result, and you could use extended regex to save you some escape characters. Since this approach, touches on several features of sed, I wanted to write it down.

for filename in $(ls); do dir=$(sed -r 's/([[:digit:]]{4})([[:digit:]]{2}).*/\1\/\2/g' <<< $filename); mkdir -p $dir; mv $filename $dir; done

First, we iterate all the files in the directory.

for filename in $(ls)

Then, we calculate the directory (e.g., 2019/03) from the filename by extracting the first 4 digits ([[:digit:]]{4}) into variable 1 and the next two digits ([[:digit:]]{2}) into variable 2. Note the use of parentheses to indicate variable storage.

Note the use of the -r flag in the command which indicates the use of extended regex so we don’t have to escape our parentheses and curly braces. If you’re not using GNU sed, you might use -E or something else instead.

sed -r

Note the .* at the end of the expression so our result replaces the entire line and not just the year and month parts.


We refer to our stored variables using \1 and \2 in our result string to make a directory path year/month.


Note the here-string syntax used to indicate sed should use the literal string as input instead of interpreting it as the name of the file from which to read and match data.

<<< $filename

Now that we have our directory name, we make it with mkdir using the -p flag to make any intermediary directories. And finally, we do the move.