learningtech
learningtech

Reputation: 33725

Bash command to move only some files?

Let's say I have the following files in my current directory:

1.jpg
1original.jpg
2.jpg
2original.jpg
3.jpg
4.jpg

Is there a terminal/bash/linux command that can do something like

if the file [an integer]original.jpg exists,
    then move [an integer].jpg and [an integer]original.jpg to another directory.

Executing such a command will cause 1.jpg, 1original.jpg, 2.jpg and 2original.jpg to be in their own directory.

NOTE This doesn't have to be one command. I can be a combination of simple commands. Maybe something like copy original files to a new directory. Then do some regular expression filter on files in the newdir to get a list of file names from old directory that still need to be copied over etc..

Upvotes: 9

Views: 1096

Answers (6)

tzelleke
tzelleke

Reputation: 15345

This should work for any strictly numeric prefix, i.e. 234.jpg

for f in *original.jpg; do
  pre=${f%original.jpg}
  if [[ -e "$pre.jpg" && "$pre" -eq "$pre" ]] 2>/dev/null; then
    mv "$f" "$pre.jpg" targetDir
  fi
done

"$pre" -eq "$pre" gives an error if not integer

EDIT:
this fails if there exist original.jpg and .jpg both.
$pre is then nullstring and "$pre" -eq "$pre" is true.

Upvotes: 2

lewurm
lewurm

Reputation: 1113

well, not directly, but it's an oneliner (edit: not anymore):

for i in [0-9].jpg; do
  orig=${i%.*}original.jpg
  [ -f $orig ] && mv $i $orig another_dir/
done

edit: probably I should point out my solution:

  • for i in [0-9].jpg: execute the loop body for each jpg file with one number as filename. store whole filename in $i
  • orig={i%.*}original.jpg: save in $orig the possible filename for the "original file"
  • [ -f $orig ]: check via test(1) (the [ ... ] stuff) if the original file for $i exists. if yes, move both files to another_dir. this is done via &&: the part after it will be only executed if the test was successful.

Upvotes: 3

chepner
chepner

Reputation: 532303

Turning on extended glob support will allow you to write a regular-expression-like pattern. This can handle files with multi-digit integers, such as '87.jpg' and '87original.jpg'. Bash parameter expansion can then be used to strip "original" from the name of a found file to allow you to move the two related files together.

shopt -s extglob
for f in +([[:digit:]])original.jpg; do
    mv $f ${f/original/} otherDirectory
done

In an extended pattern, +( x ) matches one or more of the things inside the parentheses, analogous to the regular expression x+. Here, x is any digit. Therefore, we match all files in the current directory whose name consists of 1 or more digits followed by "original.jpg".

${f/original/} is an example of bash's pattern substitution. It removes the first occurrence of the string "original" from the value of f. So if f is the string "1original.jpg", then ${f/original/} is the string "1.jpg".

Upvotes: 6

njahnke
njahnke

Reputation: 1387

integer=0; while [ $integer -le 9 ] ; do if [ -e ${integer}original.jpg ] ; then mv -vi ${integer}.jpg ${integer}original.jpg lol/ ; fi ; integer=$[ $integer + 1 ] ; done

Note that here, "lol" is the destination directory. You can change it to anything you like. Also, you can change the 9 in while [ $integer -le 9 ] to check integers larger than 9. Right now it starts at 0* and stops after checking 9*.

Edit: If you want to, you can replace the semicolons in my code with carriage returns and it may be easier to read. Also, you can paste the whole block into the terminal this way, even if that might not immediately be obvious.

Upvotes: -1

houbysoft
houbysoft

Reputation: 33430

The following would work and is easy to understand (replace out with the output directory, and {1..9} with the actual range of your numbers.

for x in {1..9}
do
if [ -e ${x}original.jpg ]
then
mv $x.jpg out
mv ${x}original.jpg out
fi
done

You can obviously also enter it as a single line.

Upvotes: 1

Caleb
Caleb

Reputation: 1088

You can use Regex statements to find "matches" in the files names that you are looking through. Then perform your actions on the "matches" you find.

Upvotes: -1

Related Questions