1

I need to rename a bunch of files with the following pattern:

sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_bold.json

to


sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_bold.json

Each filename only contains one type of substring out of 4 possibilities - run-01_ (or run-02_, run-03_, run-04)

Note that the substring run-0[1-4]_ can repeat itself random amount of times in a given file.

I am out of my wits and the closest thing I can find is this question on Stack Overflow. However, based on my limited knowledge in string manipulation, I would love to have more help!!!

3
  • Please edit your question and explain what we should remove. Do we look for the specific string _run-01? Can we also have run-02? Other strings? The more detail you give us, the better we will be able to help you.
    – terdon
    Oct 14, 2021 at 14:35
  • Hey @terdon thanks for your comment!! Edits added and let me know if anything is unclear. Oct 14, 2021 at 14:40
  • Thanks, that's much clearer. One more thing though, please tell us (edit it into your question) what operating system you are using and, if Linux, which one. That will help us know what tools you have available.
    – terdon
    Oct 14, 2021 at 14:49

3 Answers 3

1

Or perl:

$ f=sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_bold.json
$ g=$(perl -pe 's/(_run-0[1-4])\1+/$1/' <<< "$f")
$ echo "$g"
sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_bold.json

with the perl-flavoured rename(1) program:

$ touch "$f"
$ ls sub*json
sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_run-01_bold.json
$ rename 's/(_run-0[1-4])\1+/$1/' sub*json
$ ls sub*json
sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_bold.json
0

Using parameter expansion:

for i in *.json; do
  a="${i##*_run}"
  b="${i%%_run*}"
  n="$b""_run$a"
  # mv -- "$i" "$n"
  printf "%s" "$n"
done
sub-2795479_ses-V1_task-rest_acq-REST1_dir-AP_run-01_bold.json

For renaming then:

mv -- "$i" "$n"

Note: do backups of the files when performing remove/moving operations.

0

If things get more complicated than rename can handle directly, I tend to just write a short script with basically the same pattern

for file in *.json
do
   changedname="$(echo "$file" | sed 's/regex/replacement/flags')"
   mv -- "$file" "$changedname"
done

in your case, you're looking for the string run-0[1-4]_, and would replace it with the empty string ``, and your flags would include g for "do this as many times it takes until you reach the end of line", so

sed 's/run-0[1-4]_//g'

is what you're aiming for.

If the first occurrence is not to be removed, then that's not hard, either!

sed -e 's/\(run-0[1-4]_.*\)run-0[1-4]_/\1/g'
3
  • My understanding is that the first occurrence should not be removed.
    – Ned64
    Oct 14, 2021 at 15:44
  • @Ned64 ah, well, fixed that. Oct 14, 2021 at 15:46
  • I'm testing and it's not giving the desired result. Oct 14, 2021 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.