【问题标题】:UNIX: How to search and copy all files with the same name to a different directoryUNIX:如何搜索所有同名文件并将其复制到不同的目录
【发布时间】:2016-05-25 06:15:33
【问题描述】:

我想我会把它放在这里来帮助其他可能需要它的人。

我有一个名为电子表格.csv 的文件,它位于我服务器上的 500 个不同位置。经过一系列的试验和错误,我确定了这个解决方案来复制这个文件的每个实例,重命名它(按增量)并将它复制到不同的文件夹中。

希望这对某人有所帮助!

COUNTER=0; 
for f in $(find folder/ -name 'spreadsheet.csv'); 
do 
  cp -v $f /new/location/spreadsheet$COUNTER.csv; 
  COUNTER=$[$COUNTER+1]; 
done

【问题讨论】:

  • 请遵循本网站的格式。在问题中提出问题,然后在下面提供答案。
  • 请注意,Bash $[…arithmetic…] 表示法已弃用,取而代之的是 $((…arithmetic…))((…arithmetic…)) — 请参阅 arithmetic expansion。不再记录带有单方括号的$[…]

标签: bash unix ssh


【解决方案1】:

一个简单的bash for-loop 就可以做到这一点:-

COUNTER="0"
fileName="spreadsheet.csv"
for file in $(find folder/ -name "$fileName" -type f -printf '%P\n'); 
do
  sourcePath=$(dirname $(readlink -f "$file")) 
  cp -v $sourcePath/$fileName /new/location/"$fileName$COUNTER" 
  COUNTER=$((COUNTER+1)) 
done

脚本的关键部分是获取每个文件的源路径,我是通过readlinkdirname 实现的。请参阅他们的man 页面以了解更多关于他们的描述。

例子:-

$ find . -name "spreadsheet.csv" -type f
./foo/spreadsheet.csv
./bar/spreadsheet.csv
./woo/spreadsheet.csv
./spreadsheet.csv

 $ ./script.sh
`/home/dude/foo/spreadsheet.csv' -> `/new/location/spreadsheet.csv0'
`/home/dude/bar/spreadsheet.csv' -> `/new/location/spreadsheet.csv1'
`/home/dude/woo/spreadsheet.csv' -> `/new/location/spreadsheet.csv2'
`/home/dude/spreadsheet.csv' -> `/new/location/spreadsheet.csv3'

【讨论】:

  • 目录名称中的空格字符或其他特殊字符会破坏这一点:mkdir foo\ bar ; touch foo\ bar/speadsheet.csv
  • 我对符号链接的特殊情况编码感到困惑。为什么有必要?当您使用cp 访问符号链接时,它将在符号链接末尾复制文件,而不是复制符号链接信息。所以,使用readlinkdirname 似乎有点过头了——系统会毫不费力地自动处理(所以只要你把fileName 改为'spreadsheet'cp -v "$file" "$new_location/$fileName$COUNTER.csv" 就可以正常工作,因为数字需要在.csv 扩展之前)。
【解决方案2】:

如果至少一个目录名称中有空格或特殊字符,则脚本将中断。

Inian 也与symlinks 相同。

下面有一个安全且标准的解决方案,只搜索常规文件:

find folder/ -type f -name 'spreadsheet.csv' -printf "%p\0" | xargs -0 sh -c '
  newlocdir=/new/location;
  COUNTER=$(ls -1 "${newlocdir}"/spreadsheet*.csv 2>/dev/null | awk "END {print NR}") ;
  for f ; do
    cp -v "${f}" "${newlocdir}"/spreadsheet$COUNTER.csv;
    COUNTER=$(($COUNTER+1));
  done' dummyarg0

-printf "%p\0" 打印找到的文件的路径名,并附加 NULL。

xargs -0 能够读取找到的文件并将 NULL 字符视为条目之间的分隔符。

| awk "END {print NR}" 打印从管道读取的行数。

COUNTER=$(ls -1 "${newlocdir}"/spreadsheet*.csv 2>/dev/null | awk "END {print NR}") 将新位置中已存在的spreadsheet*.csv 文件的数量存储到 COUNTER 变量中。

for f ; do读取位置参数; xargs提供的文件名。

sh -c ' .... ' dummyarg0 make sh 执行提供的命令。 dummyarg0 是强制性的第一个参数。 sh 将特殊参数 0 的值设置为 dummyarg0(未使用)。

测试:

$ find folder/
folder/
folder/dir2
folder/dir2/spreadsheet.csv
folder/foo bar
folder/foo bar/spreadsheet.csv
folder/spreadsheet.csv
folder/tr"uc
folder/tr"uc/spreadsheet.csv
folder/fo'o
folder/fo'o/spreadsheet.csv
folder/dir1
folder/dir1/spreadsheet.csv
$ find folder/ -type f -name 'spreadsheet.csv' -printf "%p\0" | xargs -0 sh -c '
  newlocdir=.;
  COUNTER=$(ls -1 "${newlocdir}"/spreadsheet*.csv 2>/dev/null | awk "END {print NR}") ;
  for f ; do
    cp -v "${f}" "${newlocdir}"/spreadsheet$COUNTER.csv;
    COUNTER=$(($COUNTER+1));
  done' dummyarg0
`folder/dir2/spreadsheet.csv' -> `./spreadsheet0.csv'
`folder/foo bar/spreadsheet.csv' -> `./spreadsheet1.csv'
`folder/spreadsheet.csv' -> `./spreadsheet2.csv'
`folder/tr"uc/spreadsheet.csv' -> `./spreadsheet3.csv'
`folder/fo\'o/spreadsheet.csv' -> `./spreadsheet4.csv'
`folder/dir1/spreadsheet.csv' -> `./spreadsheet5.csv'

【讨论】:

    猜你喜欢
    • 2019-11-17
    • 1970-01-01
    • 2013-06-24
    • 2020-10-20
    • 2019-02-17
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2012-09-29
    相关资源
    最近更新 更多