I looked all day from tutorials to ready made bash scripts, but couldn't find what I need. Also I never wrote a bash script before... :/
Here's my problem (to quote from full metal jacket: "there are many like it, but this one is mine"): I have a directory with 120 files that come in triplets (in bold I marked what's unique to every file triplet):
GSM6025613_SJWLM030043_D1_barcodes.tsv
GSM6025613_SJWLM030043_D1_features.tsv
GSM6025613_SJWLM030043_D1_matrix.mtx
GSM6025615_SJWLM071563_D1_barcodes.tsv
GSM6025615_SJWLM071563_D1_features.tsv
GSM6025615_SJWLM071563_D1_matrix.mtx
...
I would like to have a bash script that creates new directories with names according to the triplets unique strings (f.e. '613', '615') moves the three corresponding files (*barcode.tsv, *features.tsv, *matrix.mtx) to the corresponding directory and renames them so that the files are just called "barcode.tsv", "features.tsv" and "matrix.mtx".
I tried it with a for loop, but I'm pretty blank on bash scripting and beyond the second line, honestly, it's all jibberish to me (for now)... :/
#!/bin/bash for f in *.{tsv,mtx} do ... done
I appreciate any help!
CodePudding user response:
You can use sed
to split the file name into its components, something like this
file='GSM6025615_SJWLM071563_D1_barcodes.tsv'
eval $(sed -E 's/(GSM....)([0-9] )_(.*)_(.*)_(.*)\.tsv/n=\2;f=\5;/' <<< "$file")
echo $n
615
echo $f
barcodes
eval
allows you to take the output of sed
(the n
and f
variable assignments) and convert it to variables.
CodePudding user response:
Try this Shellcheck-clean code (maybe on a copy of your directory first!):
#! /bin/bash -p
shopt -s nullglob
for file in GSM6025[0-9][0-9][0-9]_*_{features.tsv,matrix.mtx,barcodes.tsv}
do
dir=${file#GSM6025}
dir=${dir%%_*}
newfile=${file##*_}
mkdir -p -v -- "$dir"
mv -n -v -- "$file" "$dir/$newfile"
done
shopt -s nullglob
makes globs expand to nothing when nothing matches (otherwise they expand to the glob pattern itself, which is almost never useful in programs).- See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)) for explanations of
${file#GSM6025}
etc.