cp和mv

时间:2016-02-29 20:00:05

标签: linux shell cp mv

我正在编写一个脚本来处理20个文件。它们都位于不同的目录中。我有部分文件名。

  1. 在日志目录中,File1_Date_time.err更改为File1__Date_time_orig.err
  2. cd ../scripts/
  3. sh File.sh
  4. File1目录是/data/data1directory/Sample_File1/logs/File1_Data_time.err
    File2目录是/data/data2directory/Sample_File2/logs/File2_Data_time.err
    .....

    我的脚本看起来像这样。 (runrunrun.sh)

    #!/bin/bash
    INPUT=$1
    mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
    cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
    sh /data/*/Sample_*/scripts/*_orig.sh
    

    运行时,我试过了。
    ./runrunrun.sh文件1 。 runrunrun.sh File1
    sh runrunrun.sh File1

    mv:无法移动/data/data1directory/Sample_File1/logs/File1_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err:没有此类文件或目录 cp也得到了类似的反馈

    我这样做是否正确?

    谢谢!

6 个答案:

答案 0 :(得分:6)

让我们谈谈通配符如何工作一分钟。

cp *.txt foo
如果存在与该glob匹配的任何文件,

实际上不会使用参数cp调用*.txt。相反,它运行如下:

cp a.txt b.txt c.txt foo

同样,类似

mv *.txt *.old

...不可能知道该怎么做,因为当它被调用时,它看到的是:

mv a.txt b.txt c.txt *.old

或者更糟糕的是,如果您已经拥有名为z.old的文件,那么它会看到:

mv a.txt b.txt c.txt z.old

因此,您需要使用不同的工具。考虑:

# REPLACES: mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
for f in /data/*/Sample_*/logs/*_Data_time.err; do
  mv "$f" "${f%_Data_time.err}_Data_time_orig.err"
done

# REPLACES: cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
for f in /data/*/Sample_*/scripts/*.sh; do
  cp "$f" "${f%.sh}_orig.sh"
done

# REPLACES: sh /data/*/Sample_*/scripts/*_orig.sh
for f in /data/*/Sample_*/scripts/*_orig.sh; do
  if [[ -e "$f" ]]; then
    # honor the script's shebang and let it choose an interpreter to use
    "$f"
  else
    # script is not executable, assume POSIX sh (not bash, ksh, etc)
    sh "$f"
  fi
done

在添加新名称之前,它使用parameter expansion去除旧名称的尾部。

答案 1 :(得分:1)

在您想对通配符(或更复杂)的文件名匹配执行操作的简单情况下,可以非常简洁地使用find命令。以下技术可以用于内存...几乎!

通过让find命令在找到的每个文件名上运行另一个命令来工作。您可以使用echo而非mv来空运行此示例。

如果我们想将当前目录中所有以'report'开头的文件移动到另一个名为'reports'的并行目录:

find . -name "report*.*" -exec mv '{}' ../reports/ \;

通配符字符串必须用引号引起来,标记“找到”的文件名的{}必须用引号引起来,并且必须转义最后的分号-所有这些都是由于对这些字符进行了Bash / shell处理。

查看find的手册页以了解更多用途:https://linux.die.net/man/1/find

答案 2 :(得分:1)

使用 awk 和 sed

使用 ls 过滤,使用 awk 为每条记录构建移动命令,最后的 sed 'e' 将执行该命令。

ls  *.avro  | awk ' { print "mv "$1" aa_"$1 }' | sed 'e'

首先尝试不使用 sed -- 一旦您知道您的命令显示正确,请添加 sed。

答案 3 :(得分:0)

试试这个:

更改这些:

zc_cd_delim_01.csv
zc_cd_delim_04.csv

进入这些:

zc_cd_delim_113_01.csv
zc_cd_delim_113_04.csv

命令行:

for f in zc_cd_delim_??.csv; do var1=${f%%??.*}; 
    mv $f "${var1}113_${f#$var1}"; 
done

答案 4 :(得分:0)

这就是我所使用的,非常容易写和记住

用于复制:

ls *.txt | xargs -L1 -I{} cp {} {}.old 

移动:

ls *.txt | xargs -L1 -I{} mv {} {}.old 

说明:

xargs(1) -L1 -I{}  

通过标准输入构建并执行命令行

-L max-lines
       Use  at most max-lines nonblank input lines per command line.  Trailing blanks cause an input line
       to be logically continued on the next input line.  Implies -x.

-I replace-str
       Replace occurrences of replace-str in the initial-arguments with names read from  standard  input.
       Also,  unquoted  blanks  do  not  terminate  input  items;  instead  the  separator is the newline
       character.  Implies -x and -L 1.

基本上以-L1来发送自变量,而-I{}使{}成为占位符

答案 5 :(得分:0)

也许这是一种简单的方法。

# this is in the shell file.

bash -c "cp -fR $RUN_FOLDER/* $SVN_FOLDER/"