如何将文件从X sub_dir移动到Y sub_dir

我有主DIR X和里面,我有许多子目录像A,B,C,D。 我有主要的目录Y和里面这个我有许多子目录与X主目录子目录像A,B,C,D相同的名称。

现在我只需要将X主dir子目录中的文件移动到Y主目录子目录。

例如:

在主目录X中,子目录A有100个文件

而B有1个文件

C有5个文件

和D有50个文件…

我的光标应该在主DIR X,从那里我需要将所有的子目录文件移动到Y主目录里面的同名的子目录(A,B,C,D)。

我怎么能在SHELL SCRIPTING(KSH​​)或unix中做到这一点?

Solutions Collecting From Web of "如何将文件从X sub_dir移动到Y sub_dir"

注意:从根本上修改以提出一个更简单的解决方案。 一线(更复杂)在底部。

符合POSIX的解决方案

#!/bin/sh # Specify source and target directories (example values) dirFrom='/tmp/from' dirTo='/tmp/to' # Use globbing to find all subdirectories - note the trailing '/' # to ensure that only directories match. for subdir in "$dirFrom"/*/; do # Extract the mere name. # Note that using ${subdir##*/} is NOT an option here, because $subdir ends in '/'. name=$(basename -- "$subdir") # Make sure a subdirectory of the same # name exists in the target dir. mkdir -p "$dirTo/$name" # Move all items in the source subdir. to the analogous target subdir. mv "$subdir"* "$dirTo/$name/" done 

因此,以上将与ksh一起使用,还有其他与POSIX兼容的shell(如bashzsh

这个解决方案有两个潜在的问题

  • 隐藏的项目(以.开头的项目)被忽略
  • 如果没有子目录,脚本将会中断。 或者如果它们中的任何一个是空的 ,因为诸如*任何不匹配的匹配模式都保持不变,导致不存在的路径被传递给mv

更强大的Bash版本

Bash – 与ksh不同的是,不幸的是,有两个选项可以解决这两个问题:

  • shopt -s dotglob会导致在执行通配时隐藏项目。
  • shopt -s nullglob会导致与任何内容不匹配的模式扩展为字符串。
 #!/usr/bin/env bash # Specify source and target directories (example values) dirFrom='/tmp/from' dirTo='/tmp/to' shopt -s dotglob # include hidden items when matching `*` shopt -s nullglob # expand patterns that don't match anything to the emtpy string # Use globbing to find all subdirectories - note the trailing '/' # to ensure that only directories match. for subdir in "$dirFrom"/*/; do # Extract the mere name. # Note that using ${subdir##*/} is NOT an option here, because $subdir ends in '/'. name=$(basename -- "$subdir") # Make sure a subdirectory of the same # name exists in the target dir. mkdir -p "$dirTo/$name" # Collect the paths of the items in the subdir. in # an array, so we can test up front whether anything matched. itms=( "$subdir"* ) # Move all items in the source subdir. to the analogous target subdir, # but only if the subdir. contains at least 1 item. [[ ${#itms[@]} -gt 0 ]] && mv "${itms[@]}" "$dirTo/$name/" done 
  • 请注意, shopt -s nullglob本身是不够的 – 我们仍然必须首先收集数组中的globbing匹配,所以我们可以确定是否有任何匹配。
    • 虽然我们可以使用2>/dev/nullmv在没有匹配的情况下默默的失败,但这不是可取的,因为它可以掩盖真正的错误条件。

如果你对单行程序感兴趣,这里有基于find的命令; 但是,它们相当复杂。

 # Note: Both solutions below ignore symlinks to directories as subdirectories. # [POSIX-compliant] Excluding hidden items. # Note how `\! -name '.*'` is explicitly added to the `find` command to ensure that no hidden subdirs. are matched, so as to # to match the shell globbing behavior of excluding hidden items. find "$dirFrom" -mindepth 1 -maxdepth 1 -type d \! -name '.*' -exec sh -c \ 'f=$1 t=$2/${1##*/}; set -- "$f"/*; [ -e "$1" ] && mkdir -p "$t" && mv "$@" "$t"' \ - {} "$dirTo" \; # [Bash] Including hidden items. find "$dirFrom" -mindepth 1 -maxdepth 1 -type d -exec bash -O dotglob -c \ 'f=$1 t=$2/${1##*/}; set -- "$f"/*; [[ -e $1 ]] && mkdir -p "$t" && mv "$@" "$t"' \ - {} "$dirTo" \; 

这是一个应该工作的shell脚本。 我没有时间去检查它。 请检查并确认。

 #!/bin/bash ################################################################## # # Please make sure this script is run from source # directory. Also you need to have read, write and # execute permission for this directory. # # If the subdirectories with same names are not present # then those will be created directly. ################################################################## # Replace name of source directory by "X" sourcedir="X" # Replace name of destination directory with complete path by "Y" destdir="/home/user/Y" # Copying names of all subdirectories in a temporary text file ls -Rl | grep "[az]:" | sed 's/://' | cut -c 2- > temp.txt # Moving files directory by directory to destination while read line; do mv $sourcedir$line/* $destdir$line/ echo "All files from directory $sourcedir$line moved to $destdir$line" done < temp.txt rm temp.txt 

你可以使用脚本如下:

 #!/bin/bash dirX=X dirY=Y for subdir in `ls $dirX`; do mv $dirX$subdir/* $dirY$subdir done 

用你的目录替换X,Y.