1

I have a file with links like this:

http://domain.com/file_name1.mkv
http://domain.com/file_name2.mkv
http://domain.com/file_name3.mkv

... and so on.

I want to create a file for each link with extension .strm and each file to have the name of the file name and to contain the link for that file. So, for the first link the first file name will be file_name1.strm and contain the first link, for the second link the file name will be file_name2.strm and will contain the second link, and so on. How can i do that?

I have a command that is doing something close but it creates only files with the names from words in a file:

sed -e 's/$/.strm/' file | xargs -d '\n' touch
1
  • Upvoted for asking a clear question with a well-defined problem description and showing good research effort / attempted solution. Dec 30, 2018 at 1:45

3 Answers 3

2

To elaborate your xargs attempt

xargs -L1 sh -c 'f="${0##*/}"; printf "%s\n" "$0" > "${f%.*}.strm"' < file

The first substitution f="${0##*/}" removes the path components of the URL, while the second "${f%.*}.strm" removes and replaces the extension.

Ex.

$ xargs -L1 sh -c 'f=${0##*/}; printf "%s\n" "$0" > "${f%.*}.strm"' < file
$ head *.strm
==> file_name1.strm <==
http://domain.com/file_name1.mkv

==> file_name2.strm <==
http://domain.com/file_name2.mkv

==> file_name3.strm <==
http://domain.com/file_name3.mkv
0
2

I'll try to rehabilitate the pure-bash solution proposed by @Erwan:

while IFS= read -r link; do
    filename="${link##*/}"
    echo "$link" > "${filename%.mkv}.strm"
done < file
  1. See https://unix.stackexchange.com/a/209184/230365 for explanation why one should use IFS= read -r to read a line
  2. ${var##<pattern>} substitutes a variable with longest prefix matching the removed. See "Remove matching prefix pattern" in section "Parameter Expansion" in bash(1). There are a lot of other useful parameter expansion modificators
  3. ${var%<pattern>} substitutes a variable with shortest suffix matching the removed ("Remove matching suffix pattern")
0

Edited to fix the errors mentioned in the comments, but bellka's answer is a better version of this solution.

The following reads the links in file line by line. Each link is written to a file named with the base name of the link followed by the required ending.

while read link; do
   echo "$link" >$(basename "${link%.mkv}").strm
done <file

The same as a one liner:

cat file | while read link; do echo "$link" >$(basename "${link%.mkv}").strm; done
4
  • 2
    Issues: The links contain /, so the shell will interpret them as files in weirdly named subdirectories. The variables are unquoted, which may possibly be problematic if any link contains a filename globbing character. No input data is given to the loop. No explanation given in the answer.
    – Kusalananda
    Dec 28, 2018 at 18:43
  • 2
    it also doesn't extract the filename from the end of the link, as requested.
    – Jeff Schaller
    Dec 28, 2018 at 20:47
  • I've removed my downvote as the edit has resolved the issues outlined by Kusalananda (although it does not resolve the one outlined by Jeff). Dec 30, 2018 at 1:47
  • I've seen the subsequent edits so I've now upvoted this answer. BTW, you don't need the cat for a one-liner version. An extra semi-colon is enough: while read link; do echo "$link" >"$(basename "${link%.mkv}").strm"; done <file. Nice work on improving this answer. Jan 4, 2019 at 12:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .