Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find files differing only by extension [closed]

Tags:

shell

unix

Suppose I have multiple random .txt files, and in the same directory I have nearly-identically-named files like filename.sql and filename.txt. How would I find those .sql and their counterpart .txt files without selecting any other .txt files? (The intent here is to move them to a separate folder. There is a guaranteed 1:1 relationship between the relevant .sql and .txt files, meaning that I'm not worried about moving one of the random .txt files mentioned initially.)

like image 670
verbsintransit Avatar asked May 22 '13 21:05

verbsintransit


2 Answers

Very simple:

$ mv `ls *.sql|sed s/.sql$/.txt/g` dir

To see and understand how it works, how the shell expands the line before executing mv, start the line with echo:

$ ls
a.sql b.sql a.txt b.txt c.txt
$ echo mv `ls *.sql|sed s/.sql/.txt/g` dir
mv a.txt b.txt dir

Something more "robust" if the file names have spaces (generally not a good idea in Unix, but happens) or you have hundreds of files in the directory:

$ for f in *.sql; do mv "$(echo $f|sed s/.sql$/txt/)" dir; done

To move the .sql files along with the corresponding .txt files:

$ for f in *.sql; do mv "$f" "$(echo $f|sed s/.sql$/txt/)" dir; done
like image 159
piokuc Avatar answered Sep 25 '22 18:09

piokuc


piokuc's answer works great, but if you get an argument list too long error (happens if you're moving a lot of files at once), this works as well:

ls *.sql | sed s/.sql/.txt/g | xargs -I% mv % /path/to/new/directory

Explanation:

  1. List all files name ending with .sql extension.
  2. Replace .sql with .txt in the filename list (this doesn't rename the files, just operates on the piped input).
  3. xargs

    • xargs is a program that runs other programs. We are going to run the mv (move file) command through it.
    • The -I option tells xargs to run the mv command individually for every single file name being passed by sed.
    • The % refers to actual object/filename being passed to xargs, so upon each iteration this is going to be one of the substituted file names.
    • Notice that there are 2 %: one is attached next to -I, which tells xargs to use the ampersand character as a token for a file name. The second occurrence is with mv, where the actual (and by now changed) file name gets substituted for the token.

    Esentially, xargs is saying, "For each one of the piped-in file names, run mv NEW_FILE_NAME.txt /path/to/new/directory."

like image 29
Arman H Avatar answered Sep 22 '22 18:09

Arman H