Pipe last 11 characters in filename to a text file - bash

Have a directory full of file names that end with .mp3 and have a code in it that i would like to pipe into a text file.
I need to get the last 11 characters before the .mp3 part of a file in a certain directory and pipe that into a text file (with bash on mac osx)
How do I accomplish this? With sed?

If I'm understanding correctly, you have a list of files with names like "abcdefghijklmnopqrstuvwxyz.mp3" and want to extract "pqrstuvwxyz". You can do this directly in bash without invoking any fancy sed business:
for F in *.mp3; do STRIP=${F/.mp3}; echo ${STRIP: -11}; done > list.txt
The first STRIP variable is the name of each file F with the .mp3 extension removed. Then you echo the last 11 characters and save to a file.
There's a nice page on bash substitutions here. sed is great but I personally find it's overkill for these simple cases.

Along with good above answers, can be done via awk
for f in `ls *.mp3`;
echo $f|awk -F. '{printf substr($1,length($1)-11,length($1)),$2;}'
done

Related

Renaming filename before first occurrence of character

I'm trying to rename a batch of files using a bash script or just in the command line but can't seem to find anything on how to remove characters before the first occurrence of a character.
Right now my files are named:
author1_-_year_-_title_name.txt
author2_-_year_-_title_name.txt
And I want them to look like
_-_year_-_title_name.text
or even
year_-_title_name.text
I've tried sed in the command line:
sed 's/^[^_-_]* _-_ //' *
but this only tried to edit the text files, not the file name
You can't change filenames using sed. Try this simple loop instead:
for fp in ./*_-_*; do
echo mv "$fp" "${fp#*_-_}"
done
If the output looks good, remove echo.
Could you please try rename command as follows.
rename -n s/[^-]*-_// *.txt
Output will be as follows.
rename(author1_-_year_-_title_name.txt, year_-_title_name.txt)
rename(author2_-_year_-_title_name.txt, year_-_title_name.txt)
Once you are Happy with above results(which will print only on terminal) remove -n option in above command and it should rename the files.

Reading the contents of a text file and assign to a variable using bash script

I want to read the contents of a text file and check for the filenames with extension .txt and find merge those .txt files.Is there a way I could do this using bash?
For example, if the text file contains,
file1.txt, file2.txt
I want to read the strings with .txt extension and find merge those files which is in another location.
I tried the below,
txt_file="/tmp/Muzi/tomerge.txt"
while read -r line;do
echo $line
done <"$txt_file"
But, this prints out the complete text file and I am completely new using bash.
There is a good deal of assuming involved, but... if I understood your question, you would have a tomerge.txt where on some lines a filename would appear, one per line, ending in .txt. If that is the case (and the filenames do not contain spaces) you can:
cat $(grep '[.]txt$' tomerge.txt)
It's not bash only (uses cat), it concatenates files corresponding to all lines ending in .txt we've collected from tomerge.txt.

Search text and append to each end of line of text file - OSX

I'm new to OSX command line tools.
I am trying to find a block of text in a file and append this text at the end of all lines in another text file. At run time I don't know what this text will be, I just know it will be located within "BEGINHMM" and "ENDHMM". Also, I don't know the makeup of the destination file, except for that it will not be an empty text file.
The command which finds the block of text of interest is:
sed -n '/<BEGINHMM>/,/<ENDHMM>/p' proto
where "proto" is a text file containing the text of interest.
I've been trying to pipe the output of the above command to another 'sed' command, in the following manner:
xargs -I '{}' sed -i .bak 's/$/{}/' monophones0.txt
but I am getting some bizarre results, I see the "{}" inserted in the text for example.
I've also tried piping to:
xargs -0 sed -i .bak 's/$/&/' monophones0.txt
but I just get the printout (similar to terminal echo) of the text I am trying to grab.
Ultimately I want to loop over several 'proto' files in multiple directories and copy the text between the "BEGINHMM", "ENDHMM" block in each directory, and append the selected text to that directory's monophones.txt lines.
I am running the commands in the terminal, bash, OSX 10.12.2
Any help would be appreciated.
(1) Your sed command is of the form sed -n '/A/,/B/p'; this will include the lines on which A and B occur, even if these strings do not appear at the beginning of the line. This form may have other surprises in store for you as well (what do expect will happen if B is missing or repeated?), but the remainder of this post assumes that's what you want.
(2) It's not clear how you intend to specify the "proto" files, but you do indicate they might be in several directories, so for the remainder of this post, I'll assume they are listed, one per line, in a file named proto.txt in each directory. This will ensure that you don't run into any limitations on command-line length, but the following can easily be modified if you don't want to create such a file.
(3) Here is a script which will use the sed command you've mentioned to copy segments from each of the "proto" files specified in a directory to monophones0.txt in the directory in which the script is executed.
#!/bin/bash
OUT=monophones0.txt
cat proto.txt | while read file
do
if [ -r "$file" ] ; then
sed -n '/<BEGINHMM>/,/<ENDHMM>/p' "$file" >> $OUT
elif [ -n "$file" ] ; then
echo "NOT FOUND: $file" >&2
fi
done
Just like what you did before. tmpfile=$(mktemp); sed -n '/<BEGINHMM>/,/<ENDHMM>/p' proto >$tmpfile; sed -i .bak "r $tmpfile" monophones0.txt; rm $tmpfile. This is the basic idea; there are other checks you need to perform to make this a robust script.
– 4ae1e1

How to do a loop with filenames in shellscript ordered by 'last modified'?

i'm new in Linux, and i've been trying to run a script which processes all the files in a folder using ImageMagick's convert (I rather do this task in Shell than using mogrify, because as far as I know it doesn't save different files). The files have to be processed in 'last modified' order, so I used this code:
for file in `ls -1tr {*.jpg,*.png}`; do
# imagemagick processes with the filename...
done
This code breaks for files with spaces, and according to this answer using ls is wrong for these purposes.
I also tried this solution from this response, but apparently I got it totally wrong (It raised an 'ambiguous redirect' error) and I decided I needed help.
while read LINE; do
...
done `(ls -1tr {*.png,*.jpg}`
So how do I get an ordered list of filenames for a loop? (It doesn't necessarily have to be a FOR...IN loop, it can be a WHILE, or anything.)
try this :
for file in `ls -1tr {*.jpg,*.png} | awk '{print $9}'`; do
# imagemagick processes with the filename...
done
ls -lrth give's 9 coulmns in output, out of which you need only 9th column(file names), you can get that using awk
If you have space seperated filenames, modify awk print to print all data after 9th column

Shell script to extract a filename from log message lines

I have txt file which listed with some line. Each line has image names included. What I want is, The shell script that edit same txt file OR copy particular image name to new file.
This is my txt file having list of images with their paths.
And I want output like this:
I want only image names should be extract from those lines.
You can use this awk,
awk '{ split($1,arr,"/"); print arr[length(arr)] }' yourfile > output.txt
Using gnu sed you can do:
sed -r 's~^[^[:blank:]]*/([^/ ]+) .*$~\1~' file
1.png
1#2x.png
2.png
2#2x.png
3.png
You can do something like:
cat the_file.txt|while read file; do
echo $(basename $file)
done
And (if needed) redirect the output on another file.
while read fn rest
do
basename "$fn"
done < file.txt
This will read your input line by line. It will put the filename (including path) into the fn variable, and whatever is on the rest of the line into rest. Then it uses the basename command to strip off the path and just print out the filename itself.
This is another sed solution that doesn't use extended regular expression (more portable solution):
sed 's/^.*\/\([^[:blank:]\/]*\)[[:blank:]].*$/\1/' sourceFile > destFile
You have to replace sourceFile and destFile white the path to oridinal and destination file respectively.
The command look for any string without blank char or slashes \([^[:blank:]\/]*\) preceeded by a slash ^.*\/ and followed by a blank char [[:blank:]].*$ than the patter is substitituded with the first matching string /\1/.
You could read a quick sed reference here.

Resources