Linux "mv" command, created a new file (when no folder is available) [closed] - linux

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 years ago.
Improve this question
I am using Mac terminal, inside using linux commands to find list of ".jpg" files and try to move to "myimages" folder in current directory with below command.
find . -name "*.jpg" -type f -exec mv {} myimages \;
At the time of executing above command I don't have a folder named "myimages" .
Now all my .jpg files are disappeared and there is a new file "myimages" is created in the current directory.
i guess all my images are converted into single file with name "myimages".
how to get back all images back from "myimgages" file?
Please help me.

Your images are gone. Each image gets moved to the file myimages, effectively overwriting the existing file. You can try with recovery software to get them back.
In the future, use the command find . -name "*.jpg" -type f -exec mv {} myimages/ \; instead (note the trailing slash). You can also provide the -i flag to mv, so it prompts before overwriting existing files.

Your photos are gone. Your command renamed all of them, one by one, to myimages.
You can:
Try to recover from backups
Try PhotoRec, an image recovery tool
Try Exif Untrasher, an image recovery tool
Try some other image recovery tool
Btw, you cannot run "linux commands" on a Mac. On a Mac you are running Mac commands (compiled for Mac OS X), or shell scripts. Also the ubuntu tag didn't make any sense for your question.
In the future you can avoid such mistakes by putting a trailing slash at the end of the destination if it's supposed to be a directory:
find . -name "*.jpg" -type f -exec mv {} myimages/ \;
This way you would get an error message saying:
mv: rename blah to myimages/: No such file or directory
and nothing would be moved, and you would still have your fields.

Restore them from backup.
The commands you executed are
mv file1 myimages # rename file
mv file2 myimages # rename file, discarding the old file previously referred to by myimages
and so on.
Besides the trailing slash mentioned by knittl, I'd recommend for the next time to use
find . -name "*.jpg" -type f -exec mv -t myimages/ {} +
which clearly states "doubly" that myimages is the target directory and which allows for multiple files to be moved at one mv execution.

how to get back all images back from "myimgages" file?
You can't. Since the target directory myimages did not exist, every output from find resulted in something like:
mv ./file1.jpg myimages
mv ./file2.jpg myimages
...
In each of these commands, the target was myimages. Since it didn't exist as a directory, mv assumed that it was the target filename.
You could fix the command by saying:
find . -name "*.jpg" -type f -exec mv -t myimages {} \;

Related

A script that deletes all the regular files (not the directories) with a .js extension that are in the current directory and its subfolders [duplicate]

This question already has answers here:
How to loop through a directory recursively to delete files with certain extensions
(16 answers)
Closed 2 years ago.
Write a script that deletes all the regular files (not the directories) with a .js extension that are present in the current directory and all its subfolders.
The answer should only contain one command after the shebang line, I've tried the following:
#!/bin/bash
rm -R *.js
… and:
#!/bin/bash
rm -f *.js
find . -name "*.js" -delete
Find all files in the current and child directories with the extension .js and delete the files.
The best way to achieve this remains the find command:
find . -type f -name '*.js' -exec rm -f {} \;
If however you want to stick to rm alone, it remains possible if you know exactly how many subdirectories lie under the place you're working in. For instance:
rm -f */*/*.js

finding files and moving their folders [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 years ago.
Improve this question
I have a huge number of text files, organized in a big folder tree, on Debian Linux. What I need is to find all text files having a specific name pattern and then move the containing folder to a destination.
Example:
/home/spenx/src/a12/a1a22.txt
/home/spenx/src/a12/a1a51.txt
/home/spenx/src/a12/a1b61.txt
/home/spenx/src/a12/a1x71.txt
/home/spenx/src/a167/a1a22.txt
/home/spenx/src/a167/a1a51.txt
/home/spenx/src/a167/a1b61.txt
/home/spenx/src/a167/a1x71.txt
The commands:
find /home/spenx/src -name "a1a2*txt"
mv /home/spenx/src/a12 /home/spenx/dst
mv /home/spenx/src/a167 /home/spenx/dst
The result:
/home/spenx/dst/a12/a1a22.txt
/home/spenx/dst/a167/a1a22.txt
Thank you for your help.
SK
combination of find, dirname and mv along with xargs should solve your problem
find /home/spenx/src -name "a1a2*txt" | xargs -n 1 dirname | xargs -I list mv list /home/spenx/dst/
find will fetch list of files
dirname will extract path of file. Note that it can only take one argument at a time
mv will move source directories to destination
xargs is the key to allow output of one command to be passed as arguments to next command
For details of options used with xargs, refer to its man page of just do man xargs on terminal
You can execute:
find /home/spenx/src name "a1a2*txt" -exec mv {} /home/spenx/dst \;
Font: http://www.cyberciti.biz/tips/howto-linux-unix-find-move-all-mp3-file.html
Create this mv.sh script in the current directory that will contain this:
o=$1
d=$(dirname $o)
mkdir /home/spenx/dst/$d 2>/dev/null
mv $o /home/spenx/dst/$d
Make sure it is executable by this command:
chmod +x mv.sh
Next call this command:
find /home/spenx/src -name "a1a2*txt" -exec ./mv.sh {} \;
find /home/spenx/src -name "a1a2*txt" -exec mv "{}" yourdest_folder \;
There's probably multiple ways to do this, but, since it seems you might have multiple matches in a single directory, I would probably do something along this line:
find /home/spenx/src -name "a1a2*txt" -print0 | xargs -0 -n 1 dirname | sort -u |
while read d
do
mv "${d}" /home/spenx/dst
done
It's kind of long, but the steps are:
Find the list of all matching files (the find part), using -print0 to compensate for any names that have spaces or other odd characters in them
extract the directory part of each file name (the xargs ... dirname part)
sort and uniquify the list to get rid of duplicates
Feed the resulting list into a loop that moves each directory in turn

find a pattern in files and rename them [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I use this command to find files with a given pattern and then rename them to something else
find . -name '*-GHBAG-*' -exec bash -c 'echo mv $0 ${0/GHBAG/stream-agg}' {} \;
As I run this command, I see some outputs like this
mv ./report-GHBAG-1B ./report-stream-agg-1B
mv ./reoprt-GHBAG-0.5B ./report-stream-agg-0.5B
However at the end, when I run ls, I see the old file names.
You are echo'ing your 'mv' command, not actually executing it. Change to:
find . -name '*-GHBAG-*' -exec bash -c 'mv $0 ${0/GHBAG/stream-agg}' {} \;
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:
rename 's/GHBAG/stream-agg/' *-GHBAG-*
In reply to anumi's comment, you could in effect search recursively down directories by matching '**':
rename 's/GHBAG/stream-agg/' **/*-GHBAG-*
This works for my needs, replacing all matching files or file types. Be warned, this is a very greedy search
# bashrc
function file_replace() {
for file in $(find . -type f -name "$1*"); do
mv $file $(echo "$file" | sed "s/$1/$2/");
done
}
I will usually run with find . -type f -name "MYSTRING*" in advance to check the matches out before replacing.
For example:
file_replace "Slider.js" "RangeSlider.ts"
renamed: packages/react-ui-core/src/Form/Slider.js -> packages/react-ui-core/src/Form/RangeSlider.ts
renamed: stories/examples/Slider.js -> stories/examples/RangeSlider.ts
or ditch the filetype to make it even greedier
file_replace Slider RangeSlider
renamed: packages/react-ui-core/src/Form/Slider.js -> packages/react-ui-core/src/Form/RangeSlider.js
renamed: stories/examples/Slider.js -> stories/examples/RangeSlider.js
renamed: stories/theme/Slider.css -> stories/theme/RangeSlider.css

How can I run dos2unix on an entire directory? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 2 years ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have to convert an entire directory using dos2unix. I am not able to figure out how to do this.
find . -type f -print0 | xargs -0 dos2unix
Will recursively find all files inside current directory and call for these files dos2unix command
If it's a large directory you may want to consider running with multiple processors:
find . -type f -print0 | xargs -0 -n 1 -P 4 dos2unix
This will pass 1 file at a time, and use 4 processors.
As I happened to be poorly satisfied by dos2unix, I rolled out my own simple utility. Apart of a few advantages in speed and predictability, the syntax is also a bit simpler :
endlines unix *
And if you want it to go down into subdirectories (skipping hidden dirs and non-text files) :
endlines unix -r .
endlines is available here https://github.com/mdolidon/endlines
A common use case appears to be to standardize line endings for all files committed to a Git repository:
git ls-files -z | xargs -0 dos2unix
Keep in mind that certain files (e.g. *.sln, *.bat) are only used on Windows operating systems and should keep the CRLF ending:
git ls-files -z '*.sln' '*.bat' | xargs -0 unix2dos
If necessary, use .gitattributes
It's probably best to skip hidden files and folders, such as .git. So instead of using find, if your bash version is recent enough or if you're using zsh, just do:
dos2unix **
Note that for Bash, this will require:
shopt -s globstar
....but this is a useful enough feature that you should honestly just put it in your .bashrc anyway.
If you don't want to skip hidden files and folders, but you still don't want to mess with find (and I wouldn't blame you), you can provide a second recursive-glob argument to match only hidden entries:
dos2unix ** **/.*
Note that in both cases, the glob will expand to include directories, so you will see the following warning (potentially many times over): Skipping <dir>, not a regular file.
For any Solaris users (am using 5.10, may apply to newer versions too, as well as other unix systems):
dos2unix doesn't default to overwriting the file, it will just print the updated version to stdout, so you will have to specify the source and target, i.e. the same name twice:
find . -type f -exec dos2unix {} {} \;
I think the simplest way is:
dos2unix $(find . -type f)
I've googled this like a million times, so my solution is to just put this bash function in your environment.
.bashrc or .profile or whatever
dos2unixd() {
find $1 -type f -print0 | xargs -0 dos2unix
}
Usage
$ dos2unixd ./somepath
This way you still have the original command dos2unix and it's easy to remember this one dos2unixd.
I have had the same problem and thanks to the posts here I have solved it. I knew that I have around a hundred files and I needed to run it for *.js files only.
find . -type f -name '*.js' -print0 | xargs -0 dos2unix
Thank you all for your help.
for FILE in /var/www/html/files/*
do
/usr/bin/dos2unix FILE
done
If there is no sub-directory, you can also take
ls | xargs -I {} dos2unix "{}"

Find all files with name containing string [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 2 years ago.
Improve this question
I have been searching for a command that will return files from the current directory which contain a string in the filename. I have seen locate and find commands that can find files beginning with something first_word* or ending with something *.jpg.
How can I return a list of files which contain a string in the filename?
For example, if 2012-06-04-touch-multiple-files-in-linux.markdown was a file in the current directory.
How could I return this file and others containing the string touch? Using a command such as find '/touch/'
Use find:
find . -maxdepth 1 -name "*string*" -print
It will find all files in the current directory (delete maxdepth 1 if you want it recursive) containing "string" and will print it on the screen.
If you want to avoid file containing ':', you can type:
find . -maxdepth 1 -name "*string*" ! -name "*:*" -print
If you want to use grep (but I think it's not necessary as far as you don't want to check file content) you can use:
ls | grep touch
But, I repeat, find is a better and cleaner solution for your task.
Use grep as follows:
grep -R "touch" .
-R means recurse. If you would rather not go into the subdirectories, then skip it.
-i means "ignore case". You might find this worth a try as well.
The -maxdepth option should be before the -name option, like below.,
find . -maxdepth 1 -name "string" -print
find $HOME -name "hello.c" -print
This will search the whole $HOME (i.e. /home/username/) system for any files named “hello.c” and display their pathnames:
/Users/user/Downloads/hello.c
/Users/user/hello.c
However, it will not match HELLO.C or HellO.C. To match is case insensitive pass the -iname option as follows:
find $HOME -iname "hello.c" -print
Sample outputs:
/Users/user/Downloads/hello.c
/Users/user/Downloads/Y/Hello.C
/Users/user/Downloads/Z/HELLO.c
/Users/user/hello.c
Pass the -type f option to only search for files:
find /dir/to/search -type f -iname "fooBar.conf.sample" -print
find $HOME -type f -iname "fooBar.conf.sample" -print
The -iname works either on GNU or BSD (including OS X) version find command. If your version of find command does not supports -iname, try the following syntax using grep command:
find $HOME | grep -i "hello.c"
find $HOME -name "*" -print | grep -i "hello.c"
OR try
find $HOME -name '[hH][eE][lL][lL][oO].[cC]' -print
Sample outputs:
/Users/user/Downloads/Z/HELLO.C
/Users/user/Downloads/Z/HEllO.c
/Users/user/Downloads/hello.c
/Users/user/hello.c
If the string is at the beginning of the name, you can do this
$ compgen -f .bash
.bashrc
.bash_profile
.bash_prompt
An alternative to the many solutions already provided is making use of the glob **. When you use bash with the option globstar (shopt -s globstar) or you make use of zsh, you can just use the glob ** for this.
**/bar
does a recursive directory search for files named bar (potentially including the file bar in the current directory). Remark that this cannot be combined with other forms of globbing within the same path segment; in that case, the * operators revert to their usual effect.
Note that there is a subtle difference between zsh and bash here. While bash will traverse soft-links to directories, zsh will not. For this you have to use the glob ***/ in zsh.
find / -exec grep -lR "{test-string}" {} \;
grep -R "somestring" | cut -d ":" -f 1

Resources