How to rename multiple files using find
I want to rename multiple files (file1 . fileN to file1_renamed . fileN_renamed) using find command:
But getting this error:
This not working because filename is not interpreted as shell variable.
5 Answers 5
The following is a direct fix of your approach:
However, this is very expensive if you have lots of matching files, because you start a fresh shell (that executes a mv ) for each match. And if you have funny characters in any file name, this will explode. A more efficient and secure approach is this:
It also has the benefit of working with strangely named files. If find supports it, this can be reduced to
The xargs version is useful when not using <> , as in
Here rm gets called once (or with lots of files several times), but not for every file.
I removed the basename in you question, because it is probably wrong: you would move foo/bar/file8 to file8_renamed , not foo/bar/file8_renamed .
Edits (as suggested in comments):
- Added shortened find without xargs
- Added security sticker
Find multiple files and rename them in Linux
I am having files like a_dbg.txt, b_dbg.txt . in a Suse 10 system. I want to write a bash shell script which should rename these files by removing «_dbg» from them.
Google suggested me to use rename command. So I executed the command rename _dbg.txt .txt *dbg* on the CURRENT_FOLDER
My actual CURRENT_FOLDER contains the below files.
After executing the rename command,
Its not doing recursively, how to make this command to rename files in all subdirectories. Like XX and YY I will be having so many subdirectories which name is unpredictable. And also my CURRENT_FOLDER will be having some other files also.
9 Answers 9
You can use find to find all matching files recursively:
EDIT: what the ‘<>‘ and \; are?
The -exec argument makes find execute rename for every matching file found. ‘<>‘ will be replaced with the path name of the file. The last token, \; is there only to mark the end of the exec expression.
All that is described nicely in the man page for find:
For renaming recursively I use the following commands:
small script i wrote to replace all files with .txt extension to .cpp extension under /tmp and sub directories recursively
Scipt above can be written in one line:
find -execdir rename to rename files and directories with a regular expression
If you are going to rename both files and directories with regular expressions, and not simply with a suffix, then this is a good pattern:
Sample usage to replace spaces ‘ ‘ with hyphens ‘-‘.
Dry run that shows what would be renamed to what without actually doing it:
The awesome -execdir option does a cd into the directory before executing the rename command, unlike -exec .
-depth ensure that the renaming happens first on children, and then on parents, to prevent potential problems with missing parent directories.
-execdir is required because rename does not play well with non-basename input paths, e.g. the following fails:
The PATH hacking is required because -execdir has one very annoying drawback: find is extremely opinionated and refuses to do anything with -execdir if you have any relative paths in your PATH environment variable, e.g. ./node_modules/.bin , failing with:
find: The relative path ‘./node_modules/.bin’ is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove that entry from $PATH
-execdir is a GNU find extension to POSIX. rename is Perl based and comes from the rename package.
Rename lookahead workaround
If your input paths don’t come from find , or if you’ve had enough of the relative path annoyance, we can use some Perl lookahead to safely rename directories as in:
The sort -r is required to ensure that files come after their respective directories, since longer paths come after shorter ones with the same prefix.
find a pattern in files and rename them [closed]
Want to improve this question? Update the question so it’s on-topic for Stack Overflow.
Closed 3 years ago .
I use this command to find files with a given pattern and then rename them to something else
As I run this command, I see some outputs like this
However at the end, when I run ls , I see the old file names.
4 Answers 4
You are echo’ing your ‘mv’ command, not actually executing it. Change to:
I would suggest using the rename command to perform this task. rename renames the filenames supplied according to the rule specified as a Perl regular expression.
In this case, you could use:
In reply to anumi’s comment, you could in effect search recursively down directories by matching ‘**’:
This works for my needs, replacing all matching files or file types. Be warned, this is a very greedy search
I will usually run with find . -type f -name «MYSTRING*» in advance to check the matches out before replacing.
or ditch the filetype to make it even greedier
Not the answer you’re looking for? Browse other questions tagged linux bash or ask your own question.
Linked
Related
Hot Network Questions
site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2020.9.18.37632
Find and rename a directory
I am trying to find and rename a directory on a linux system.
the folder name is something like : thefoldername-23423-431321
thefoldername is consistent but the numbers change every time.
The command actually works and rename that directory. But I got an error on terminal saying that there is no such file or directory.
5 Answers 5
It’s a harmless error which you can get rid of with the -depth option.
Find’s normal behavior is to process directories and then recurse into them. Since you’ve renamed it find complains when it tries to recurse. The -depth option tells find to recurse first, then process the directory after.
It’s missing the -execdir option! As stated in man pages of find:
Like -exec , but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find.
find . -depth -type d -name ‘thefoldername*’ -execdir mv <> newfoldername \;
With the previous answer my folders contents are disappeared.
This is my solution. It works well: for i in find -type d -name ‘oldFolderName’ ; do dirname=$(dirname «$i») mv $dirname/oldFolderName $dirname/newFolderName done
Replace 1100 with old_value and 2200 with new_value that you want to replace.
[user@server test]$ ls -la check/drwxr-xr-x. 1 user user 0 Jun 7 12:16 1100
[user@server test]$ for i in $(find . -type d -iname ‘1100’);do echo «mv «$i» «$i»__» >> test.txt; sed ‘s/1100__/2200/g’ test.txt > test_1.txt; bash test_1.txt ; rm test*.txt ; done [user@server test]$ ls -la check/drwxr-xr-x. 1 user user 0 Jun 7 12:16 2200
here __ in sed is used only to change the name it have no other significance
How to rename multiple files using find and rename
I want to take out .hs from all files. Why this command doesn`t work properly? It leaves the same name of files.
2 Answers 2
In an -exec command, the place where you want your file name to go should be marked with <> .
Also, as I am guessing that you want .hs removed, not replaced with a space, we have removed the space between the single-quotes.
Documentation
man find includes an explanation of the -exec option:
-exec command ;
Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ; is encountered. The string <> is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a \ ) or quoted to protect them from expansion by the shell. See the EXAMPLES section for examples of the use of the -exec option. The specified command is run once for each matched file. The command is executed in the starting directory. There are unavoidable security problems surrounding use of the -exec action; you should use the -execdir option instead. [Emphasis added.]
How to find,copy and rename files in linux?
I am trying to find all files in a directory and sub-directories and then copy them to a different directory. However some of them have the same name, so I need to copy the files over and then if there are two files have the same name, rename one of those files.
So far I have managed to copy all found files with a unique name over using:
However, I now need some sort of if statement to figure out if a file has the same name as another file that has been copied.
4 Answers 4
Since you are on linux, you are probably using cp from coreutils. If that is the case, let it do the backup for you by using cp —backup=t
Try this approach: put the list of files in a variable and copy each file looking if the copy operation succeeds. If not, try a different name.
Inside the for statement, you can also put some incremental integer to try different names incrementally (e.g., name_1, name_2 and so on, until the cp command succeeds).
in your script in place of the find command to append integer suffixes to identically-named files
You can use rsync with the following switches for more control
With this option, preexisting destination files are renamed as each file is transferred or deleted. You can control where the backup file goes and what (if any) suffix gets appended using the —backup-dir and —suffix options.
—backup-dir=DIR
In combination with the —backup option, this tells rsync to store all backups in the specified directory on the receiving side. This can be used for incremental backups. You can additionally specify a backup suffix using the —suffix option (otherwise the files backed up in the specified directory will keep their original filenames).
—suffix=SUFFIX
This option allows you to override the default backup suffix used with the —backup (-b) option. The default suffix is a
if no —backup-dir was specified, otherwise it is an empty string.
You can use rsycn to either sync two folders on local file system or on a remote file system. You can even do syncing over ssh connection.
rsync is amazingly powerful. See the man page for all the options.