将特定目录中的一种文件复制到另一个目录
Copying a type of file, in specific directories, to another directory
我有一个包含目录列表的 .txt 文件。我想制作一个脚本来遍历此 .txt 文件,将目录中列出的某种文件类型的所有内容复制到另一个目录。
我从来没有对目录做过,只对文件做过。
我如何编辑这个简单的脚本来读取目录列表、查找 .csv 文件并将其复制到另一个目录?
cat filenames.list | \
while read FILENAME
do
find . -name "$FILENAME" -exec cp '{}' new_dir\;
done
for DIRNAME in $(dirname.list); do find $DIRNAME -type f -name "*.csv" -exec cp \{} dest \; ; done;
抱歉,在我的第一个回答中,我不明白您的要求。
第一行代码,简单地说,将目录列表中的目录名条目作为路径,并在其中搜索每个以“.csv”扩展名结尾的文件;然后将其复制到您想要的目的地。
但是你可以用更少的代码来做:
for DIRNAME in $(dirname.list); do cp $DIRNAME/*.csv dest ; done
尽管列表的文件名是 filenames.list
,但我假设该文件包含目录名列表,而不是文件名。那你试试看:
while IFS= read -r dir; do
find "$dir" -type f -name "*.mp3" -exec cp -p -- {} new_dir \;
done < filenames.list
find
命令在“$dir”中搜索扩展名为 .mp3
的文件,然后将它们复制到 new_dir
.
上面的脚本不关心文件名的重复。如果您想保留原始目录树and/or需要文件名重复的对策,请告诉我。
在 while 循环中使用 find 可以工作,但是 find 会在文件的每一行上 运行,另一种方法是将列表保存在数组中,这样 find 就可以在列表中的目录中搜索一次搜索。
如果你有 bash4+,你可以使用 mapfile。
mapfile -t directories < filenames.list
如果你卡在 bash3 上。
directories=()
while IFS= read -r line; do
directories+=("$lines")
done < filenames.list
现在,如果您只是在寻找一种文件类型,例如以 *.csv
.
结尾的文件
find "${directories[@]}" -type f -name '*.csv' -exec sh -c 'cp -v -- "$@" /newdirectory' _ {} +
如果您有多个文件类型要匹配并且有多个目录要复制文件。
while IFS= read -r -d '' file; do
case $file in
*.csv) cp -v -- "$file" /foodirectory;; ##: csv file copy to foodirectory
*.mp3) cp -v -- "$file" /bardirectory;; ##: mp3 file copy to bardirectory
*.avi) cp -v -- "$file" /bazdirectory;; ##: avi file copy to bazdirectory
esac
done < <(find "${directories[@]}" -type f -print0)
在处理带有空格和换行符的文件时,find 的 print0
将与 read 的 -d ''
一起工作。见 How can I find and deal with file names containing newlines, spaces or both?
--
在那里,所以如果你有一个有问题的文件名,以破折号开头 -
cp
不会将它解释为 option
.
考虑到 find
处理多个文件夹的能力,并假设目标是 'flatten' 将所有 csv 文件放入一个目的地,请考虑以下内容。
请注意,它假定文件夹名称没有特殊字符(包括 space、制表符、换行符等)。
附带的好处是,它将最大限度地减少 'cp' 调用的次数,从而使处理过程在大量 files/folders.
中变得高效
find $(<filename.list) -name '*.csv' | xargs cp -t DESTINATION/
对于更复杂的情况,文件夹 names/file 名称可以是任何内容(包括 space、'*' 等),请考虑使用 NUL 分隔符(-print0 和 -0)。
xargs -I{} -t find '{}' -name '*.csv' <dd -print0 | xargs -0 -I{} -t cp -t new/ '{}'
这将分叉多个 find
和多个 cp
。
我有一个包含目录列表的 .txt 文件。我想制作一个脚本来遍历此 .txt 文件,将目录中列出的某种文件类型的所有内容复制到另一个目录。
我从来没有对目录做过,只对文件做过。
我如何编辑这个简单的脚本来读取目录列表、查找 .csv 文件并将其复制到另一个目录?
cat filenames.list | \
while read FILENAME
do
find . -name "$FILENAME" -exec cp '{}' new_dir\;
done
for DIRNAME in $(dirname.list); do find $DIRNAME -type f -name "*.csv" -exec cp \{} dest \; ; done;
抱歉,在我的第一个回答中,我不明白您的要求。 第一行代码,简单地说,将目录列表中的目录名条目作为路径,并在其中搜索每个以“.csv”扩展名结尾的文件;然后将其复制到您想要的目的地。 但是你可以用更少的代码来做:
for DIRNAME in $(dirname.list); do cp $DIRNAME/*.csv dest ; done
尽管列表的文件名是 filenames.list
,但我假设该文件包含目录名列表,而不是文件名。那你试试看:
while IFS= read -r dir; do
find "$dir" -type f -name "*.mp3" -exec cp -p -- {} new_dir \;
done < filenames.list
find
命令在“$dir”中搜索扩展名为 .mp3
的文件,然后将它们复制到 new_dir
.
上面的脚本不关心文件名的重复。如果您想保留原始目录树and/or需要文件名重复的对策,请告诉我。
在 while 循环中使用 find 可以工作,但是 find 会在文件的每一行上 运行,另一种方法是将列表保存在数组中,这样 find 就可以在列表中的目录中搜索一次搜索。
如果你有 bash4+,你可以使用 mapfile。
mapfile -t directories < filenames.list
如果你卡在 bash3 上。
directories=()
while IFS= read -r line; do
directories+=("$lines")
done < filenames.list
现在,如果您只是在寻找一种文件类型,例如以 *.csv
.
find "${directories[@]}" -type f -name '*.csv' -exec sh -c 'cp -v -- "$@" /newdirectory' _ {} +
如果您有多个文件类型要匹配并且有多个目录要复制文件。
while IFS= read -r -d '' file; do
case $file in
*.csv) cp -v -- "$file" /foodirectory;; ##: csv file copy to foodirectory
*.mp3) cp -v -- "$file" /bardirectory;; ##: mp3 file copy to bardirectory
*.avi) cp -v -- "$file" /bazdirectory;; ##: avi file copy to bazdirectory
esac
done < <(find "${directories[@]}" -type f -print0)
在处理带有空格和换行符的文件时,find 的 print0
将与 read 的 -d ''
一起工作。见 How can I find and deal with file names containing newlines, spaces or both?
--
在那里,所以如果你有一个有问题的文件名,以破折号开头 -
cp
不会将它解释为 option
.
考虑到 find
处理多个文件夹的能力,并假设目标是 'flatten' 将所有 csv 文件放入一个目的地,请考虑以下内容。
请注意,它假定文件夹名称没有特殊字符(包括 space、制表符、换行符等)。
附带的好处是,它将最大限度地减少 'cp' 调用的次数,从而使处理过程在大量 files/folders.
中变得高效find $(<filename.list) -name '*.csv' | xargs cp -t DESTINATION/
对于更复杂的情况,文件夹 names/file 名称可以是任何内容(包括 space、'*' 等),请考虑使用 NUL 分隔符(-print0 和 -0)。
xargs -I{} -t find '{}' -name '*.csv' <dd -print0 | xargs -0 -I{} -t cp -t new/ '{}'
这将分叉多个 find
和多个 cp
。