How to find files recursively by file type and copy them to a directory?
Try this:
find . -name "*.pdf" -type f -exec cp {} ./pdfsfolder \;
Find all files from today recursively and copy them
Remove -maxdepth 1
from your find
command to find files in subdirectories and use -exec
to move those to the target directory:
find /dir -type f -mtime -1 -exec mv {} /pdf \;
Recursively Find Files With Particular File Extension and Content
What do you mean by keyword? Is that a word, present inside the file? Or is it a part of the filename?
In case it's the part of the filename, you can use file:
in the Windows search, like in following example:
file:*keyword*.py
This will show you all files, called *keyword*.py
. After you've done that, you might change your Windows explorer's view, clicking on the "View" tab and choose "Details", this will also show you the directory where those files are located.
How to recursively copy all files with a certain extension in a directory using Python?
If I understand correctly, you want glob
with recursive=True
, which, with the **
specifier, will recursively traverse directories and find all files satisfying a format specifier:
import glob
import os
import shutil
def copy(src, dest):
for file_path in glob.glob(os.path.join(src, '**', '*.bmp'), recursive=True):
new_path = os.path.join(dest, os.path.basename(file_path))
shutil.copy(file_path, new_path)
Recursive find and copy to other directory
The above will get you everything in /media, but to get exactly what you want you probably want to use something like:
Method 1: Copy only what you need recursively, per your requirements:
mkdir ../media2; find . -name "*.jpg" -exec cp -r --parents {} ../media2 \;
I ran this from inside the directory you want to search recursively. It does a couple things:
1 - create the new destination directory
mkdir ../media2
2 - then finds all files ending with ".jpg" recursively.
find . -name "*.jpg"
3 - uses -exec to pass the copy command to each file returned to find as a match, and subs that in as the first argument (which with the syntax of cp, is going to be your source file):
-exec cp -r --parents {} ../media2 \;
the "--parents" flag retains existing directory structure and recursively creates subsequent parent directories. Super useful right?
Method 2: there might be a better way to do this with xargs, but the above ended up being the most simple method imho. That said, if you want to think outside the box, you could simply copy the entire directory over recursively, then remove anything NOT ending with ".jpg" with something like:
cp -r media media2; find ./media '!'-name "*.jpg" -type f | xargs rm
Recursively copy directories and files into destination
You could easily achieve this by implementing the FileVisitor interface. This is a code sample just to show you how it works. It should do what you asked.
EDIT: Updated with custom size handling
public class FileCopier implements FileVisitor<Path> {
private final Path sourcePath;
private final Path targetPath;
private HashMap<String, Long> mapSize;
public FileCopier(Path sourcePath, Path targetPath) throws IOException {
//Check whether the destination directory exists or not
if (!Files.exists(targetPath)) {
Files.createDirectories(targetPath);
}
this.sourcePath = sourcePath.toRealPath();
this.targetPath = targetPath.toRealPath();
this.mapSize = new HashMap<>();
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
//Copying the directory first and then its content (directory copy does not copy its content)
//Retrieving the last bit of the path starting from the source location
Path lastBitPath = sourcePath.relativize(dir.toAbsolutePath().normalize());
//Adding the last bit to the target path
Path targetCopyPath = targetPath.resolve(lastBitPath).toAbsolutePath().normalize();
if (!Files.exists(targetCopyPath)) {
Files.copy(dir, targetCopyPath, StandardCopyOption.COPY_ATTRIBUTES);
}
//Defining 0 bytes for the new visited directory
mapSize.put(targetCopyPath.toString(), 0L);
System.out.println("Started: " + targetCopyPath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path targetCopyPath = targetPath.resolve(sourcePath.relativize(file.toAbsolutePath().normalize())).toAbsolutePath().normalize();
Files.copy(file, targetCopyPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
//Adding the current copied file's bytes to the corresponding folder
mapSize.put(targetCopyPath.getParent().toString(), mapSize.get(targetCopyPath.getParent().toString()) + Files.size(file));
System.out.println("Finished FILE: " + targetCopyPath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
return FileVisitResult.TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
//Retrieving the last bit of the path starting from the source location
Path lastBitPath = sourcePath.relativize(dir.toAbsolutePath().normalize());
//Adding the last bit to the target path
Path targetCopyPath = targetPath.resolve(lastBitPath).toAbsolutePath().normalize();
//Showing the number of bytes copied within the copied directory
System.out.println("Total " + this.mapSize.get(targetCopyPath.toString()) + " bytes were copied into " + targetCopyPath);
return FileVisitResult.CONTINUE;
}
public static void main(String[] args) throws IOException {
Path sourcePath = Paths.get("./test");
Path targetPath = Paths.get("./subtest");
FileCopier fc = new FileCopier(sourcePath, targetPath);
Files.walkFileTree(sourcePath, fc);
}
}
Copy specific files from different directories without changing file extension
Assuming you want to use the subfolder name (number) as a suffix to the new
file name, would you please try:
#!/bin/bash
folder="folder" # directory name
base="1" # basename of the jpg file
ext="jpg" # extention of the jpg file
new="new" # directory name for the "new" files
mkdir -p "$folder/$new" # create "new" directory if nonexistent
while IFS= read -r -d "" f; do
n=${f#*$folder/}; n=${n%/$base.$ext}
echo cp -i -- "$f" "$folder/$new/$base($n).$ext"
done < <(find "$folder" -type f -regex "$folder/[0-9]+/$base\.$ext" -print0)
find "$folder" -type f -regex "$folder/[0-9]+/$base\.$ext"
finds
all numbered folders which contains "1.jpg". You do not have to specify
the range between 1 and 100.-print0
option uses a null character to delimit filenames. It is useful
to protect filenames which may contain special characters such as blank
characters.- The output of
find
command, matched filenames delimited by null characters,
is redirected to theread
command within thewhile
loop. - The
-d ""
option to theread
command splits the input on null characters
corresponding to-print0
. n=${f#*$folder/}; n=${n%/$base.$ext}
assignsn
to the subfolder name
which contains the jpg file."$folder/$new/$base($n).$ext"
constructs the new filename rearranging
the substrings.
If the output of the echo
command looks okay, drop echo
.
Related Topics
How to Build a Linux Kernel Module So That It Is Compatible with All Kernel Releases
Xdp Program Ip Link Error: Prog Section Rejected: Operation Not Permitted
Best Way to Set Environment Variables in Calling Shell
Suppress Notice of Forked Command Being Killed
Why Does Order in Which Input Libraries Are Specified Matter
Makefile Export .O File to a Different Path Than .Cpp
Magic Numbers of the Linux Reboot() System Call
How Can Objdump Emit Intel Syntax
Count Occurrences of Character Per Line/Field on Unix
What Are Ld-Linux.So.2 and Linux-Gate.So.1
How to Wait for First Command to Finish
Logrotate to Clean Up Date Stamped Files
What Are Meanings of Fields in /Proc/Net/Dev
How to Remove X Bytes from the End of a Large File Without Reading the Whole File