I want shotwell to open all .cr2 files in a folder and all its subfolders, what command line do I use?
Usually, you will want to just open Shotwell and drag in the folder.
If you need to, you can make the shell build a list of CR2 files and tell Shotwell to open just those files. Occasionally that may be what you want, but in this case that did not do quite what you needed due to Shotwell's behavior -- in some other circumstances, a feature -- of automatically showing you other image files (of all types) residing in the same folders as the images you opened.
To ensure Shotwell only knows about the images you are interested in, you could clone the directory tree somewhere else, copying only .cr2
files and the folders that contain them, but nothing else. That may take up substantial additional space, though. So another approach is to construct a hierarchy of symbolic links -- where instead of having having a new directory tree of copies of your original .cr2
files, you have a new directory tree of syminks to them. This takes up far less space.
This answer covers all those approaches.
Opening a Folder of Images (Including Subfolders) in Shotwell
Shotwell itself gives you two ways to open a whole directory tree of photos. If these will work for you, then you won't need to do anything clever in the command line or even use it at all. If not, you might end up doing this in connection with another technique. (For example, if you end up creating a new directory of symlinks or copies of your .cr2
files, you can use one of these ways to open it.)
Way 1: Just open the whole folder in Shotwell.
In Shotwell, in the File menu, click Import from Folder. Then select the folder you want to import images from. This won't be limited to .cr2
files, but if you're opening files from multiple subfolders containing .cr2
images created from a digital camera, then most likely those will be the only files present.
See Jakob's answer to Show all pictures recursively (include any subfolders) for more information.
Way 2: Drag the folder into Shotwell.
With most desktop environments and file browsers, you can also open Shotwell and drag the folder that contains your images into the Shotwell window. Like Import from Folder, this is another way Shotwell recommends to open photos.
When you drag from a file browser window or your desktop into Shotwell, you can drag to a specific library. Or if you don't have multiple libraries set up, you can just drag basically anywhere and it works. (You don't even have to drag into the left pane.)
This method is very convenient, and it is as powerful as manually selecting the folder (with File > Import from Folder, as described above). When you open files or folders using either of these methods, Shotwell gives you the option to open the photos without copying them into its library.
To import without copying, click Import in Place instead of Copy Photos.
Launching Shotwell with a List of Image Filenames
If for some reason you want or need to do this by running a command in the Terminal, you can run the shotwell
command and pass each image's filename to it as an argument. Globstar makes it easy:
shopt -s globstar
shotwell **/*.cr2
That opens the .cr2
files located anywhere in the current directory. It differs from running Shotwell and then dragging the folder in, in that Shotwell will only try to import the the files whose names you give it. However, since Shotwell often shows other image files from the same folders as the files you've told it to open, this may not be adequate for your needs. (And further information you've given about your problem suggests that it is not. See below for an alternative.)
This does not include files or subfolders whose names start with .
. However, if you have CR2 files whose names start with a dot, then most of the time you probably don't want to open them in Shotwell anyway. Unless you've deliberately named your files or folders in this way, a dotfile with an image or document filename extension is more likely to be a metadata file rather than an actual image or document. For example, macOS often adds such files (e.g., ._kittens.cr2
for an actual picture kittens.cr2
) when accessing external media (including flash drives and digital cameras).
If you do want to also find files whose names start with .
or that are in folders whose names start with .
, then enable dotglob as well. You can do this with shopt -s dotglob
or by passing both globstar
and dotglob
to the shopt
builtin:
shopt -s globstar dotglob
By default, globs are case-sensitive. But you might want to match filenames case-insensitively, so as to open files ending in .cr2
, .Cr2
, .cR2
, and .CR2
. To do that, either:
-
Enable nocaseglob by running
shopt -s
withnocaseglob
, either by itself or with other shell options. For example, to runshotwell
on all.cr2
files, searching case-insensitively and including.
-files and files in.
-directories:shopt -s globstar dotglob nocaseglob shotwell **/*.cr2
-
Or, use
.[cC][rR]2
instead of.cr2
in your glob pattern itself. For example, this accomplishes the same as above:shopt -s globstar dotglob shotwell **/*.[cC][rR]2
Note that case sensitivity is entirely separate from whether or not
.
files and folders are matched. You can removedotglob
from the examples above and they can still be case-insensitive.
To specify a directory rather than just using the current directory, put its name and a /
before the **/*.cr2
glob. For example, replacing the shotwell
command above with this one will open all the .cr2
files inside the Pictures
subdirectory of your home directory:
shotwell ~/Pictures/**/*.cr2
Unlike with the first command that uses your current directory, no matter where you run that command you will be telling Shotwell to open the same files.
Testing
If you really have to use the terminal for this, then I'm guessing it may be part of something more complex. If you like, you can test such commands before actually running them by replacing shotwell
with printf '%s\n'
. Instead of passing the filenames to Shotwell, that lists them one per line. For example, on my machine:
ek@Io:~$ printf '%s\n' ~/tmp/**/*.cr2
/home/ek/tmp/another image.cr2
/home/ek/tmp/image.cr2
/home/ek/tmp/some folder/image3.cr2
Turning Off Globstar and Other Shell Options
The globstar shell option has be enabled to work, which is what the shopt -s globstar
command (above) did. If it's already enabled, then you don't need multiple commands. And you only need to set globstar once per shell instance.
You can turn globstar back off by running:
shopt -u globstar
And you can check whether globstar is on or off by running:
shopt globstar
If you're using globstar in a script, you should consider turning it back off if there might be code that comes afterwards in the same script that is not written with globstar in mind. For example, writing **
when you mean *
is usually no problem when globstar is disabled, but with globstar turned on, it can cause serious problems by making a command affect far more files than someone intended.
Similarly, if you used dotglob or nocaseglob and you want too turn them off, you can do so with shopt -u dotglob
and shopt -u nocaseglob
, respectively. You can also pass multiple shell options to shopt -u
to unset them at the same time. For example, to turn off globstar,
dotglob
, and nocaseglob
:
shopt -u globstar dotglob nocaseglob
Compared to globstar, there are fewer serious mistakes you might make because you forgot you left dotglob or nocaseglob on. But other people (including people you consult on sites like Ask Ubuntu) usually assume dotglob and nocaseglob are disabled when they suggest commands for you to use, unless you tell them otherwise.
For more information on these glob-related shell options (and also on globs in general), see the bash reference manual. They are all covered primarily in 4.3.2 The Shopt Builtin. For globstar, see also 3.5.8.1 Pattern Matching. For dotglob, see also 3.5.8 Filename Expansion.
Building a New Directory Tree
Since in your case you seem to really need Shotwell to show only .cr2
files, you have non-.cr2
files in the same folders with .cr2
files, and image browsing in Shotwell is automatically offering those files too, it looks like you will need to have a folder that contains no other image files than the .cr2
files you're trying to open.
Moving the files, as you've suggested, is one approach, but I recommend instead either copying the files or, better, making symbolic links to the files (see also FOLDOC), because:
- If you're moving the files across devices, that requires copying anyway, so in that case moving is no faster.
- If you have the space, it's often a good idea to keep an unmodified folder of everything you started with until you're satisfied that what you've done is correct according to your needs. Obviously this is not always applicable or practical. But in your case, these files are the result of a data recovery operation. It may be useful to keep an easily perused record of precisely what was recovered and from where.
- If you choose to create symbolic links, the amount of additional space consumed is extremely small. (If the target disk is completely full, though, then you will still need to free up space on it -- or use a different target disk -- to create symlinks.)
There is another decision for you to make, too. Do you create all the new entries (whether they be copies or symlinks) in the same directory, flattening the file hierarchy? Or do you create directories at the destination corresponding to each of the directories at the source that contain at least one .cr2
file?
Flattening the file hierarchy lets you see all the files at once, easily. In particular, it is easy to see the files' names and sizes all at once, as well as to select any combination of the files in a graphical file browser.
But it also loses information about what folders they were in, which may be valuable (though you can return to the original folder and look for them there if you don't move the files).
-
The bigger problem with flattening the file hierarchy, though, is what happens if you have two or more files of the same name in different places. If you flatten the file hierarchy, then depending on how you do it, either all but the first will fail to be copied (or linked) and you'll get an error or warning, or all but the last copy (or link) will be overwritten.
This is another reason I recommend copying or making symlinks rather than moving files. If you "successfully" move multiple files into the same file, you've lost all but the last one!
Because of the disadvantages of flattening everything into a single directory without subdirectories, the approaches I take here build a new directory tree at the destination.
Way 1: Copying
I show this first because it's a little simpler, but I suggest you instead create symbolic links ("Way 2"), especially if the destination drive might not have enough space to hold all the files. "Way 2," which is a bit more complicated, is much more detailed because there seem to be fewer resources on how to use that technique, it's the way I expect most people in this situation will prefer, and information that applies to both methods -- basic advice about escaping spaces in paths -- is given there rather than here.
When you need to copy a directory tree and you need to customize the copy operation, you should usually use rsync
instead of cp
. This is one of those cases.
Replacing src
with the path to the top-level directory containing all your CR2 files, and replacing dest
with the name of the directory you want to create that will contain a hierarchy of symbolic links to the CR2 files, run:
rsync -rl --prune-empty-dirs --include='*/' --include='*.cr2' --exclude='*' src/ dest
Don't forget the /
after the name of the source directory, unless you want an additional top-level directory to be created inside dest
. That is, if you omit the trailing /
, then rsync
will make the destination directory for you, inside dest
. For example, suppose src
is a relative path containing no /
. Then:
- With
src/
in yourrsync
command, you get a symlinkdest/foo/bar.cr2
for the filesrc/foo/bar.cr2
. - With
src
in yourrsync
command, you get a symlinkdest/src/foo/bar.cr2
for the filesrc/foo/bar.cr2
.
Since it could be confusing for the top-level directory where symlinks will be placed to have the same name as that of the top-level directory containing the .cr2
files that the symlinks will point to, I recommend you include the /
at the end of the destination directory name in your rsync
command. (And, for the source directory, give it a directory that is empty, doesn't exist, or is otherwise dedicated to this purpose. Otherwise, you'll be cluttering up some other folder.)
As is generally the case when you pass the name of a file or directory to a command-line program or script, if your destination or source directory paths contain any blank spaces (or characters treated specially by the shell, like \
, $
, '
, and various other punctuation), then you will have to quote them. I've detailed how to do this, for the most common case of spaces, in "Way 2"--the advice about quoting in that section applies here as well. However, if you're not sure how to quote the name of a folder, you can have Ubuntu do it for you by simply dragging the folder into the Temrminal; its full path will be pasted in with correct quotation.
After copying just the .cr2
files and the folders that contain them, you can open the destination folder up in Shotwell. (See "Opening a Folder of Images (Including Subfolders) in Shotwell" above.) However, before running rsync
, I recommend you decide if want to skip entries that start with .
and if you want to include entries with case-variant suffixes. If so, you'll have to run some slightly different rsync
command.
Customizing the Handling of Dotted Entries and Case Sensitivity
You may want to use a different rsync
command to change whether or not files and directories that start with a dot are skipped and whether or not you want case-sensitivity in matching the suffix .cr2
.
The command above does include directories and files whose names start with .
. To exclude such files and directories, put --exclude='.*/' --exclude='.*'
before all other --include
s and --exclude
s. That is, use this rsync
command instead (with the appropriate substitutions for src
and dest
, of course):
rsync -rl --prune-empty-dirs --exclude='.*/' --exclude='.*' --include='*/' --include='*.cr2' --exclude='*' src/ dest
The rsync
commands shown thus far have been case-sensitive and will not copy files that end in .CR2
, .Cr2
, or .cR2
rather than .cr2
. If you want such files to be copied, then you'll need to account for that by using the --include
pattern *.[cC][rR]2
in place of *.cr2
.
This third command is case-insensitive and (like the first command) does not skip files and directories whose names start with .
:
rsync -rl --prune-empty-dirs --include='*/' --include='*.[cC][rR]2' --exclude='*' src/ dest
If you take the approach of copying files with rsync
, and you're not sure which of these commands you want, I suggest using that one if you want to make sure not to miss anything. However, you should be aware that dotfiles may contain metadata, and dotfiles named like images may not really be images. See the discussions on dotfiles in the "Launching Shotwell with a List of Image Filenames" section above, and on dotfiles and case sensitivity in "Way 2" below.
This fourth command is case-insensitive and (like the second command) does skip files and directories whose names start with .
:
rsync -rl --prune-empty-dirs --exclude='.*/' --exclude='.*' --include='*/' --include='*.[cC][rR]2' --exclude='*' src/ dest
Way 2: Creating Symbolic Links
This is what I recommend you do, though Way 1 is okay if you have enough space on the destination drive. You don't have to read Way 1 to use this.
The method presented here makes a list of .cr2
files and loops through the list, creating target directories as needed and populating them with symbolic links to each .cr2
file.
This is just complicated enough that I suggest putting it in a script rather than just typing it in interactively. You can put the script wherever you like, but for convenience, I'll show how to do it with the script placed directly in your home folder.
Write (or paste in) the script.
Create a text file, make-symlinks
, in your home folder. No file extension is needed.
You can do this with any text editor, like Vim, Nano, Gedit, or Leafpad. Don't use a word processor like LibreOffice Writer, though. (You could even do it by running cat > ~/make-symlinks
, pasting in the contents of the file, and pressing Ctrl+D on a new line, if you wanted.)
If you name the script something other than make-symlinks
, make sure to use that name when you run commands that use the script later.
#!/bin/bash
shopt -s globstar dotglob nocaseglob
for f in **/*.cr2; do
mkdir -p "$1/$(dirname "$f")"
ln -s "$PWD/$f" "$1/$f"
done
Put that in the file, and save the file. This script uses globstar, a Bash feature explained above in "Launching Shotwell with a List of Image Filenames".
You can change how it handles dotted entries and case sensitivity.
Depending on your needs, you may want to make some changes:
-
If you don't want to include
.cr2
files whose names start with.
or that reside in directories whose names start with.
, removedotglob
from theshopt
line.Files and directories whose name start with
.
are often used for metadata (see the "Launching Shotwell with a List of Image Filenames" section above). On the other hand, if you want to make sure you have everything, or if there's something inexplicably missing that you are pretty sure is there, then should keepdotglob
. If you want to include only files that end in exactly
.cr2
but not case variants (.CR2
,.Cr2
, and.cR2
), then you should removenocaseglob
. Since your situation involves data recovery and Shotwell will not show you any of the files you missed when you open up the directory of symbolic links -- that's the point of this method, after all -- you will likely want to keepnocaseglob
.
Make it executable.
Run this command to mark your script executable:
chmod +x ~/make-symlinks
Run it at the source and pass the destination as an argument.
Then change directory to the source directory, i.e., the top-level folder that contains the pictures. For example, if they are in the Pictures
subdirectory of your home directory, you would run:
cd ~/Pictures
This is where you'll run the script. Pass the destination directory to the script as a command-line argument.
For example, if you want a directory called cr2s
to be created on your Desktop to contain the symbolic links, run:
~/make-symlinks ~/Desktop/cr2s
Or if you just want that directory directly in your home folder:
~/make-symlinks ~/cr2s
Or if you have a drive mounted at /media/you/MyDrive
and you want to create a folder on it called links
to contain the symbolic links:
~/make-symlinks /media/you/MyDrive/links
But if the drive is /media/you/My Drive
(with a space) then you must use quotation. Any of these works (use just one, don't run them all):
~/make-symlinks '/media/you/My Drive/links'
~/make-symlinks /media/you/'My Drive'/links
~/make-symlinks /media/you/My\ Drive/links
But if you use ~
for your home directory, don't quote that:
~/make-symlinks ~/'Two Words' # good
~/make-symlinks ~/Two\ Words # good
~/make-symlinks '~/Two Words' # BAD, because ~ doesn't get expanded
make-symlinks
creates the destination directory for you if it doesn't already exist, just as it creates subdirectories within it. However, it still works if the destination already exists.
You can even run it multiple times and pass the same destination directory (for example, if you interrupted it with Ctrl+C), though you'll get failed to create symbolic link
errors for the symlinks that already exist, and that could be confusing.
You probably don't want to pass the name of a directory that already exists and contains unrelated files (like your home directory) to make-symlinks
. If you do, you can expect a whole bunch of symlinks and subfolders to be created in it. You probably want to use a new directory -- or one that doesn't exist yet -- for make-symlinks
.
Import the newly created symlink tree into Shotwell.
After you run make-symlinks
, just import the directory you passed to it into Shotwell, using either of the methods given in the first part of this answer ("Opening a Folder of Images (Including Subfolders) in Shotwell"). For example, you could open Shotwell and drag the folder in.
Since all the the entries in folder are either symbolic links to .cr2
files or directories that contain them, with no other file types, Shotwell should not see any of the other files.
Shotwell will cycle through all the images found in every directory where an image is open, so using find -name '*.cr2' -exec shotwell '{}' +
as I orginally suggested does not really help. Since Shotwell's settings are rather limited, the only way I can think of to open only the files you want is to move the files to a new directory by themselves.
You can use find
for that:
mkdir ~/cr2files
find -type f -iname '*.cr2' -not -path './dir/*' -exec cp -v -- '{}' ~/cr2files \;
Replace cp
with mv
if you want to avoid creating duplicate files.
Notes:
-
mkdir ~/cr2files
make a new directory in your home directory -
find
search recursively from the current directory downwards through the tree -
-type f
search only for files -
-iname
search for files by name, ignoring case -
'*.cr2'
names ending with.cr2
- use quotes to stop the shell expanding the glob before it's passed tofind
-
-not -path './dir/*'
will exclude the contents of directorydir
from the results -
{}
represents the paths of the found files -
--
aftercp
is to tellcp
not to accept any further options, which avoids any filenames beginning with-
causing issues
You can then open any file in the new directory with Shotwell and cycle through them all