Under my folder, there are a lot of files all starting with "abcd", like "abcd****".
What I am going to do is change all the files names replacing "abcd" by "xyz".
How to use shell command like "find" "sed" to do this?
A simple method would be something like this:
for i in abcd*; do mv "$i" "xyz${i#abcd}"; done
Using a combination of ls, sed and xargs you could use:
ls * | sed -e 'p;s!^abcd!xyz!' | xargs -n2 mv
Result:
abcd.png ā xyz.png
* to do a dry-run first, replace mv at the end with echo
for f in abcd*; do mv "$f" "$(echo "$f" | sed 's/^abcd/xyz/g')"; done
Related
I have a folder X with lot of files:
file01x01.txt
file02x01.txt
file03x01.txt
file04 01.txt
file05 01.txt
I would like to put a "x" between the 0401 and 0501 like the first 3 files. So far I was doing something like:
for f in *.txt ; do mv "$f" "${f// /x}" ; done
This works but it applies to all the *.txt files and I would like to avoid that. How can I do it only for file04 01.txt and file05 01.txt in my example?
I was thinking maybe something like this:
for f in file[04-05].txt ; do mv "$f" "${f// /x}" ; done
but I can't get the proper syntax.
You can use * wildcards plus a quoted space ' ' to find files that have a space in their name.
for f in file*' '*.txt; do
mv "$f" "${f// /x}"
done
You can do it in this way too:
find . -name "file*[[:space:]]*.txt" -exec bash -c 'f="{}"; mv "$f" "${f// /x}"' \;
you can use the rename tool.
if your filenames have only one space, this would be enough:
$ rename -n 's/ /x/' *txt
rename(file04 01.txt, file04x01.txt)
rename(file05 01.txt, file05x01.txt)
(-n is for "dry run", remove it to perform the actual renaming)
if your filenames have more than one space character, you can use something like this:
$ rename -n 's/ (\d*.txt)$/x$1/' *txt
rename(file04 01.txt, file04x01.txt)
rename(file05 01.txt, file05x01.txt)
rename(file with spaces 06 01.txt, file with spaces 06x01.txt)
I have files with name of the form "NAME-xxxxxx.tedx" and I want to remove the "-xxxxxx" part. The x are all digits.
The regex "\-[0-9]{1,6}" matches the substring, but I have no idea how to remove it from the filename.
Any idea how I can do that in the shell?
If you have the perl version of the rename command installed, you could try:
rename 's/-[0-9]+//' *.tedx
Demo:
[me#home]$ ls
hello-123.tedx world-23456.tedx
[me#home]$ rename 's/-[0-9]+//' *.tedx
[me#home]$ ls
hello.tedx world.tedx
This command is smart enough to not rename files if it means overwriting an existing file:
[me#home]$ ls
hello-123.tedx world-123.tedx world-23456.tedx
[me#home]$ rename 's/-[0-9]+//' *.tedx
world-23456.tedx not renamed: world.tedx already exists
[me#home]$ ls
hello.tedx world-23456.tedx world.tedx
echo NAME-12345.tedx | sed "s/-[0-9]*//g"
will give NAME.tedx. So you can use a loop and move the files using mv command:
for file in *.tedx; do
newfile=$(echo "$file" | sed "s/-[0-9]*//g")
mv "$file" $newfile
done
If you want to use just the shell
shopt -s extglob
for f in *-+([0-9]]).tedx; do
newname=${f%-*}.tedx # strip off the dash and all following chars
[[ -f $newname ]] || mv "$f" "$newname"
done
I have a folder with files named as
input (1).txt
input (2).txt
input (3).txt
...
input (207).txt
How do I rename them to
input_1.in
input_2.in
input_3.in
...
input_207.in
I am trying this
for f in *.txt ; do mv $f `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done
But it gives me
mv: target `(100).txt' is not a directory
mv: target `(101).txt' is not a directory
mv: target `(102).txt' is not a directory
...
Where did I go wrong?
I have put in the quotes now, but I get this now
mv: `input (90).txt' and `input (90).txt' are the same file
It is somehow trying to rename the file to the same name. How is that happening?
That is because bash for split the element with space ' ' so you are commanding it to move 'input' to '(1)'.
The way to solve this is to tell bash to split by new line using IFS variable.
Like this:
IFS=$'\n'
Then do your command.
However, I suggest you to use find to do this instead using -exec command.
For example:
find *.txt -exec mv "{}" `echo "{}" | sed -e 's/input\ (\([0-9]*\))\.txt/input_\1.in/'` \;
NOTE: I write this from memory and I did test this so let try and adjust it.
Hope this helps.
You're forgetting to quote your arguments.
... mv "$f" "$(echo "$f" | ... )" ; done
no need to call external commands
#!/bin/bash
shopt -s nullglob
shopt -s extglob
for file in *.txt
do
newfile="${file//[)]/}"
newfile="${file// [(]/_}"
mv "$file" "${newfile%.txt}.in"
done
As you've already fixed, you need to quote the $f argument to mv.
As to your second problem, sed doesn't support \d. You could use [0-9] instead.
for f in *.txt ; do mv "$f" `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done
If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you can do this:
seq 1 207 | parallel -q mv 'input ({}).txt' input_{}.in
Watch the intro video for GNU Parallel to learn more:
http://www.youtube.com/watch?v=OpaiGYxkSuQ
I have a renamed js file which I have to call in each of my php pages. Now I want to replace that old name with the new one using shell.
what iam using is this:
sed -i ās/old/new/gā *
but this is giving the following error:
sed: -e expression #1, char 1: unknown command:
How can I do this replacement?
sed -i.bak 's/old/new/g' *.php
to do it recursively
find /path -type f -iname '*.php' -exec sed -i.bak 's/old/new/' "{}" +;
There are probably less verbose solutions, but here we go:
for i in *; do sed -i 's/old/new/g' "$i"; done
Mind you, it will only work on the current level of the file system, files in subdirectories will not be modified. Also, you might want to replace * with *.php, or make backups (pass an argument after -i, and it will make a backup with the given extension).
this one is very simple, without for or loop, and takes care of any number or nested directories
grep -rl 'oldText' [folderName-optional] | xargs sed -i 's/oldText/newText/g'
You are using Unicode apostrophes (RIGHT SINGLE QUOTATION MARK - U2019) instead of ASCII (0x27) apostrophes around your sed command argument.
I know I'm really late but still:
find . -type f -name "*.php"|xargs sed -i 's/old/new/g'
perl -pi -e 's/old/new/g' *.php
For completeness, providing the OSX compatible version of the above accepted answer (to answer comment from #jamescampbell)
for i in *.php; do sed -i .orig 's/old/new/g' "$i"; done
This command creates .orig backup files.
Try this:
ls | grep "php" > files.txt
for file in $(cat files.txt); do
sed 's/catch/send/g' $file > TMPfile.php && mv TMPfile.php $file
done
I have a directory with a bunch of files with names like:
001234.jpg
001235.jpg
004729342.jpg
I want to remove the leading zeros from all file names, so I'd be left with:
1234.jpg
1235.jpg
4729342.jpg
I've been trying different configurations of sed, but I can't find the proper syntax. Is there an easy way to list all files in the directory, pipe it through sed, and either move or copy them to the new file name without the leading zeros?
for FILE in `ls`; do mv $FILE `echo $FILE | sed -e 's:^0*::'`; done
sed by itself is the wrong tool for this: you need to use some shell scripting as well.
Check Rename multiple files with Linux page for some ideas. One of the ideas suggested is to use the rename perl script:
rename 's/^0*//' *.jpg
In Bash, which is likely to be your default login shell, no external commands are necessary.
shopt -s extglob
for i in 0*[^0]; do mv "$i" "${i##*(0)}"; done
Maybe not the most elegant but it will work.
for i in 0*
do
mv "${i}" "`expr "${i}" : '0*\(.*\)'`"
done
Try using sed, e.g.:
sed -e 's:^0*::'
Complete loop:
for f in `ls`; do
mv $f $(echo $f | sed -e 's:^0*::')
done
I dont know sed at all but you can get a listing by using find:
find -type f -name *.jpg
so with the other answer it might look like
find . -type f -name *.jpg | sed -e 's:^0*::'
but i dont know if that sed command holds up or not.
Here's one that doesn't require sed:
for x in *.jpg ; do let num="10#${x%%.jpg}"; mv $x ${num}.jpg ; done
Note that this ONLY works when the filenames are all numbers. You could also remove the leading zeros using the shell:
for a in *.jpg ; do dest=${a/*(0)/} ; mv $a $dest ; done
In Bash shell you can do:
shopt -s nullglob
for file in 0*.jpg
do
echo mv "$file" "${file##*0}"
done