How to move files from X sub_dir to Y sub_dir

匿名 (未验证) 提交于 2019-12-03 08:59:04

问题:

I have main DIR X and inside this I have many sub directories like A,B,C,D. I have main DIR Y and inside this i have many sub directories with same name as X main directory sub directories like A,B,C,D.

Now I need to MOVE only files from X main dir sub directories to Y main directory sub directory.

Eg:

Inside main directory X ,sub directory A has 100 files

and B has 1 file

and C has 5 files

and D has 50 files...

my cursor should be at main DIR X , from there I need to MOVE all the sub directory files to same named sub directories(A,B,C,D) which is there inside Y main directory.

how can I do this in SHELL SCRIPTING(KSH) or unix??

回答1:

Note: Fundamentally revised to come up with a simpler solution. One-liners (more complex) at the bottom.

A POSIX-compliant solution:

#!/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   

The above will therefore work with ksh as well, and also other POSIX-compatible shells such as bash and zsh.

There are two potential problems with this solution:

  • Hidden items (those whose name starts with a .) are ignored.
  • The script will break, if there are no subdirs. or if any of them is empty, because a globbing pattern such as * that does not match anything is left as-is, resulting in non-existent paths being passed to mv.

More robust Bash version

Bash - unlike ksh, unfortunately - has options that address both issues:

  • shopt -s dotglob causes hidden items to be included when globbing is performed.
  • shopt -s nullglob causes patterns that don't match anything to expand to the empty string.
#!/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 
  • Note how shopt -s nullglob by itself was not enough - we still had to collect globbing matches in an array first, so we could determine if anything matched.
    • While we could instead just use 2>/dev/null to let mv fail silently if there are no matches, this is not advisable, because it could mask true error conditions.

If you're interested in one-liners, here are find-based commands; they are, however, quite complex.

# 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" \; 


回答2:

Here is a shell script which should work. I have not had time to check it though. Please check and confirm.

#!/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 "[a-z]:" | 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 


回答3:

You can use script as below:

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

Replace X, Y with your directory



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!