The following assumes, based on your description, that:
- variable
tmp
contains a newline-separated list of filenames[1]
- you want to extract the fifth path element from the filename (e.g.
ZRT834_9
and ZRT207_1
)
- you want to create a sub-directory with that path element if it doesn't already exist
- you want to symlink the filename into that newly created directory.
#!/bin/bash
tmp="/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S2_L001_I1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_I2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_I2.tar"
while read -r f ; do
d="$(echo "$f" | sed -E 's:^(/+[^/]+){4}/+([^/]*)/.*:\2:')"
[ -z "$d" ] && echo "Error: no fifth element in path: '$f'" && exit 1
mkdir -p "$d" || exit 1
ln -s "$f" "$d/"
done <<< "$tmp"
The sed
script uses Extended Regular Expressions (-E
option) and (roughly translated into English) captures the first 4 groups (the {4}
) of /+[^/]+
(one-or-more slashes followed by one-or-more non-slash characters) into capture group 1, then the next [^/]+
after one-or-more slashes into capture group two and replaces the entire input line with just capture group two (\2
).
The "one-or-more slashes" is because it's perfectly valid to have a pathname like /foo/////////////////bar////baz
- the excess /s will be ignored. BTW, some programs (e.g. smbclient
) will interpret the first element of a pathname beginning with 2 slashes as a server name prefix, but that's not the case with most programs.
[1] you really should use an array for this. e.g.
#!/bin/bash
# double-quote each array element even though your sample
# data doesn't need to be quoted - because other filenames
# might contain white-space or shell metacharacters.
tmp=("/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_R1.tar"
"/abc/bcd/def/ZRT834/ZRT834_9/5678/S2_L001_I1.tar"
"/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_I2.tar"
"/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R1.tar"
"/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R2.tar"
"/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_I2.tar")
for f in "${tmp[@]}" ; do
d="$(echo "$f" | sed -E 's:^(/+[^/]+){4}/+([^/]*)/.*:\2:')"
[ -z "$d" ] && echo "Error: no fifth element in path: '$f'" && exit 1
mkdir -p "$d" || exit 1
ln -s "$f" "$d/"
done
ZRT834_9
are unique. But, the same filenames can be repeated in other paths.