Renaming a set of files in linux - linux

I have 100 files named sub1.txt, sub2.txt,..., sub100.txt. I like to rename them as all1.txt, all2.txt,..., all100.txt. How can one do this in linux (unix)?
Thanks for your help.

The script below will rename an arbitrary number of file with the pattern sub*.txt. This also does a dry-run thanks to the echo. Simply remove the echo once you are satisfied with the results.
#!/bin/bash
for file in sub*.txt; do
echo mv "$file" "all${file#sub}"
done

Using the util-linux-ng version of rename:
rename sub all sub*.txt
Using the Perl script version of rename:
rename 's/^sub/all/' sub*.txt

for i in `seq 1 100`; do mv sub$i.txt all$i.txt; done
or
for i in sub*.txt; do j=`echo $i|sed -e s/sub/all/`; mv $i $j; done

for F in sub*.txt ; do mv $F all${F#sub}; done

Ruby(1.9+)
ruby -e 'Dir["sub*.txt"].each {|x| File.rename(x, x.gsub(/^sub/,"all") ) }'

There is always a new way to do it:
$ ls sub*.txt | tr -d "sub" | xargs -I{} mv sub{} all{}
Hope it helps.

Related

Remove certain characters in a filename in Linux

I have files in a directory such as
FILE1.docx.txt
FILE2.docx.txt
FILE3.docx.txt
FILE4.docx.txt
FILE5.docx.txt
And I would like to remove .docx from all of them to make the final output such as
FILE1.txt
FILE2.txt
FILE3.txt
FILE4.txt
FILE5.txt
How do I do this?
With Parameter Expansion and mv
for f in *.docx.txt; do
echo mv -vn "$f" "${f%%.*}.${f##*.}"
done
The one-liner
for f in *.docx.txt; do echo mv -vn "$f" "${f%%.*}.${f##*.}"; done
Remove the echo if you think the output is correct, to rename the files.
Should work in any POSIX compliant shell, without any script.
With bash, enable the nullglob shell option so the glob *.docx.txt will not expand as literal *.docx.txt if there are no files ending with .docx.txt
#!/usr/bin/env bash
shopt -s nullglob
for f in *.docx.txt; do
echo mv -vn "$f" "${f%%.*}.${f##*.}"
done
UPDATE: Thanks to #Léa Gris add nullglob change the glob to *.docx.txt and add -n to mv, Although -n and -v is not defined by POSIX as per https://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html It should be in both GNU and BSD mv
Just run this python script in the same folder that contains files:
import os
for file in os.listdir(os.getcwd()):
aux = file.split('.')
if len(aux) == 3:
os.rename(file, aux[0] + '.' + aux[2])
you can make use of sed and bash like this:
for i in *.docx.txt
do
mv "$i" "`echo $i | sed 's/.docx//'`"
done

Shell remove pattern from filename

I have a lot of files named like activity_unpublish_39x39.png, abc_29x29.png and etc.
I want to convert the name to activity_unpublish.png (remove _39x39)
and abc.png (remove _29x29).
Could anyone tell me how I can achieve that?
It would be better working on Mac OS X.
The following small shell script should work on Linux and also on Mac OS. Note that it's working in the current folder, further you have to change pat and suf to your needs (here suf="\.png" and pat="_[0-9]+x[0-9]+$suf" to work with your given example).
It uses sed with -E which is undocumented in the manpage. It's the option to go in Mac OS which is known as -r in Linux. In Linux it is also existent but as said not documented:
#!/bin/sh
suf="\.png"
pat="_[0-9]+x[0-9]+$suf"
for f in *; do
if [[ $f =~ $pat ]]; then
newName=$(echo "$f" | sed -E "s/$pat/$suf/g")
mv "$f" "$newName"
fi
done
I got the answer from my kind colleague.
Use this shell script.
#!/bin/sh
for file in *_[0-9]*x[0-9]*.png
do
mv $file $(echo $file | sed 's/_[0-9]*x[0-9]*//')
done

How do I search for a file based on what is output by a command running on that file

I am working on a project for one of my professors and he asked me to sort a couple hundred .fits images based on their header files (specifically what star they are images of) I think that grep would be the best way to do this however I can't seam to figure out how to use grep based on the header.
I am entering:
ls | imhead *.fits | grep -E -r "PG\ 1104+243" *
to just list them out for now, once they are listed I know how to copy them into a directory.
I am new to using grep so I am unsure as to where my error lies? any help would be greatly appreciated! Thanks!
Assuming that imghead will extract the headers of the .fits as txt, you can use a simple shell script to do it:
script.sh
#!/bin/bash
grep "$1" "$2" > /dev/null 2>&1 && echo "$2"
Note that the + is a special character if you use extended regular expression, meaning if you pass the -E as in the question. A simple grep without any options should do the trick here.
Use find to exec the script on every *.fits file in the current folder:
find -maxdepth 1 -name '*.fits' -exec ./script.sh 'PG 1104+243' {} \;
If you are going to copy/move/alter or do something with the files you find, you might be better off, in terms of complexity and ease of quoting, using a loop like this:
#!/bin/bash
find . -name \*.fits -print0 | while read -d '' -r file; do
echo Checking file: $file
imhead "$file" | grep -q 'PG 1104+243'
if [ $? -eq 0 ]; then
echo Object matches: $file
fi
done

Linux Bash file Reading Lines and words

I apologize if this is a trivial question. I am learning how to use linux bash and this little task is giving me a headache...
So I need to write a script, let's call it count.sh. I want that: for each file in the working directory, prints the filename, the number of lines, and the number of words to the console:
test.txt 100 1023
someOtherfiles 10 233
So far, I know that the following gives me all the files names in the directory. And thanks for all who helped me, I get this working version:
for f in *; do
echo -n "$f"
cat "$f" | wc -wl
done
I would really appreciate your help! Thanks ahead!
P.s. If you know great resources (links for tutorials) for learning about script and you are willing to share it with me. I think I really need to know these basics. Thanks again!
If you must have the file name as the first field in your output, try this:
for f in *; do
if [ -f "$f" ]; then
echo -n "$f"
cat "$f" | wc -wl
fi
done
for f in *; do
if [[ -f $f ]]; then
echo "$f $(wc -wl < "$f")"
fi
done
[[ -f $f ]] processes only files (excludes subdirectories) and also handles the case where the directory is empty (in which case * is (by default) left unexpanded, i.e. assigned to $f as is).
echo "$f $(wc -wl < "$f")" uses command substitution ($( ... )) to directly include the output from the enclosed command in the output string passed to echo.
Note that the reason that < is used to direct the content of file $f to wc via stdin is that wc would otherwise append the name of the input file to its output (thanks, #R Sahu).

Linux Write Something on multiple files

I have a file "atest.txt" that have some text..
I want to print this text at files "asdasd.txt asgfaya.txt asdjfusfdgh.txt asyeiuyhavujh.txt"
This files is not exist on my server..
I'm running Debian.. What can i do?
Use the tee(1) command, which duplicates its standard input to standard output and any files specified on the command line. E.g.
printf "Hello\nthis is a test\nthank you\n"
| tee test1.txt test2.txt $OTHER_FILES >/dev/null
Using your example:
cat atest.txt
| tee asdasd.txt asgfaya.txt asdjfusfdgh.txt asyeiuyhavujh.txt >/dev/null
From your bash prompt:
for f in test1.txt test2.txt test3.txt; do echo -e "hello\nworld" >> $f; done
If the text lives in atest.txt then do:
for f in test1.txt test2.txt test3.txt; do cat atest.txt >> $f; done
Isn't it simply:
cp atest.txt asdasd.txt
cp atest.txt asgfaya.txt
cp atest.txt asdjfusfdgh.txt
cp atest.txt asyeiuyhavujh.txt
?
In bash you can write
#!/bin/bash
$TEXT="hello\nthis is a test\nthank you"
for i in `seq 1 $1`; do echo -e $TEXT >text$i.txt; done
EDIT (in response of question change)
If you can't determine programmatically the names of the target files then you can use this script it:
#!/bin/bash
ORIGIN=$1;
shift
for i in `seq $#`; do cp "$ORIGIN" "$1"; shift; done
you can use it this way:
script_name origin_file dest_file1 second_dest_file 'third file' ...
If you are wondering why there are the double quotes into the cp command, it is for cope with filename containing spaces
If anyone would like to write same thing to all files in dir:
printf 'your_text' | tee *

Resources