Shell 命令行,写一个自动整理 ~/Downloads/ 文件夹下文件的脚本

mac 或者 linux 系统中,我们的浏览器或者其他下载软件下载的文件全部都下载再 ~/Downloads/ 文件夹下面。日积月累,我们的文件会越来越多。手工整理这些文件是比较繁琐的工作,于是,我就思考,我能不能用 shell 来自动整理这些下载的文件。

说干就干。

为了避免破坏我本地的文件,我自己搞了一个虚拟机跑了一个 centos 然后写下了如下的脚本。

第一版代码(处理文件名带空格的文件会出错)

#!/bin/bash
# Name cleardown
# Description move you files in ~/Downloads to ~/Documents/OfficeFiles
# Author FungLeo
# WebSite http://blog.csdn.net/fungleo

# find .  -maxdepth 1 -type f
# Excel  Other  PDF  Photo  PPT  Word  Xmind  Zip

# 设定要整理的文件夹为下载目录
downFinder=~/Downloads/
# 看看下载目录根目录下有哪些文件
dfiles=$(ls -l $downFinder | grep ^- | sed 's/[ ][ ]*/,/g' | awk -F "," '{print $NF}')
# 准备将这些文件处理到哪里去
filesFinder=~/Documents/OfficeFiles/

# 分辨文件类型,并给出放到哪里去的建议。这里大家可以根据自己的需求完善 case 语句
function fileType() {
  case $1 in
    'jpg' | 'png' | 'gif' | 'jpeg' | 'bmp')
      echo 'Photo'
    ;;
    'doc' | 'docx')
      echo 'Word'
    ;;
    'xls' | 'xlsx')
      echo 'Excel'
    ;;
    'ppt' | 'pptx')
      echo 'PPT'
    ;;
    'zip' | '7z' | 'rar')
      echo 'Zip'
    ;;
    'xmind')
      echo 'Xmind'
    ;;
    'pdf')
      echo 'PDF'
    ;;
    *)
      echo 'Other'
    ;;
  esac
}

# 判断目标文件夹中是否包含这个文件
function hasfile() {
  if [ -f $1 ]; then
    echo 'has'
  else
    echo 'nohas'
  fi
}

# 给文件重新命个名字,我这里是在后面加了一个 1
function changeFileName() {
  local filename=$(basename $1)
  echo ${filename%.*}1.${filename##*.}
}

# 开始搬文件的函数
function mvFile() {
  # 这个函数需要传两个参数,一个是原文件名,一个是新文件名。
  local name=$1
  local newname=$2
  # 获取文件的后缀名,并且转化为小写
  local type=$(echo $1 | awk -F "." '{print $NF}' | tr "[:upper:]" "[:lower:]" )
  local classify=$(fileType $type)
  local file=$filesFinder$classify'/'$newname
  # 判断新文件名在目标地址是否有同名文件
  local hasf=$(echo $(hasfile $file))
  if [ $hasf = 'has' ]; then
    mvFile $name $(changeFileName $newname)
  else
    mv $downFinder$name $file
  fi
}

# 循环这些文件,并且进行处理
for i in $dfiles; do
  mvFile $i $i
done

小结

其中还是使用到了很多的知识点的。

  1. case 语句。一开始用 if 判断,越写越丑。查了下 case 语句,果然清爽很多了。
  2. 获取文件后缀名。本例中用了两种方法。
    1. awk 方法。awk -F "." '{print $NF}'. 分割取最后一个。
    2. ${filename##*.} 取后缀名。${filename%.*} 取文件名
  3. 函数的写法。其实不写 function 也是可以的。
  4. 函数自己调自己,和 js 也没太大区别嘛。
  5. 字符串大小写转换 tr "[:upper:]" "[:lower:]"

2017年08月08日补充,解决文件名中包含空格的问题

#!/bin/bash
# Name cleardown
# Description move you files in ~/Downloads to ~/Documents/Office Files
# Author FungLeo
# WebSite http://blog.csdn.net/fungleo

# find .  -maxdepth 1 -type f
# Excel  Other  PDF  Photo  PPT  Word  Xmind  Zip

# 设定要整理的文件夹为下载目录
downFinder="${HOME}/Downloads/"
# 准备将这些文件处理到哪里去
filesFinder="${HOME}/Documents/Office Files/"

# 分辨文件类型,并给出放到哪里去的建议。这里大家可以根据自己的需求完善 case 语句
function fileType() {
  case $1 in
    'jpg' | 'png' | 'gif' | 'jpeg' | 'bmp')
      echo 'Photo'
    ;;
    'doc' | 'docx')
      echo 'Word'
    ;;
    'xls' | 'xlsx')
      echo 'Excel'
    ;;
    'ppt' | 'pptx')
      echo 'PPT'
    ;;
    'zip' | '7z' | 'rar')
      echo 'Zip'
    ;;
    'xmind')
      echo 'Xmind'
    ;;
    'pdf')
      echo 'PDF'
    ;;
    *)
      echo 'Other'
    ;;
  esac
}

# 判断目标文件夹中是否包含这个文件
function hasfile() {
  if [ -f $1 ]; then
    echo 'has'
  else
    echo 'nohas'
  fi
}

# 给文件重新命个名字,我这里是在后面加了一个 1
function changeFileName() {
  local filename=$(basename $1)
  echo ${filename%.*}1.${filename##*.}
}

# 开始搬文件的函数
function mvFile() {
  # 这个函数需要传两个参数,一个是原文件名,一个是新文件名。
  local name=$1
  local newname=$2
  # 获取文件的后缀名,并且转化为小写
  local type=$(echo $1 | awk -F "." '{print $NF}' | tr "[:upper:]" "[:lower:]" )
  local classify=$(fileType $type)
  local file="$filesFinder$classify/$newname"
  # 判断新文件名在目标地址是否有同名文件
  local hasf=$(echo $(hasfile $file))
  if [ $hasf = 'has' ]; then
    mvFile $name $(changeFileName $newname)
  else
    mv "$downFinder$name" "$file"
  fi
}

# 设置分隔符为换行
OLD_IFS=$IFS
IFS=$'\n'
# 循环这些文件,并且进行处理
for i in $(find "$downFinder" -maxdepth 1 -type f -not -name ".*" | awk -F "/" '{print $NF}'); do
  mvFile $i $i
done

# 将分隔符设置为默认,以免影响后面的程序
IFS=$OLD_IFS

补充小结

  1. 我先前没有考虑文件夹或者文件包含空格的情况,导致很多问题。

    1. 当把路径用引号 " 引起来的时候,不会解析 ~ 所以要用 ${HOME} 代替
    2. 在引用变量的时候,变量也要用引号引起来。注意,不能是单引号。
  2. 默认分隔符为空白,包含:空格、制表符、回车符,用 IFS 表示。
  3. echo 最终命令,和实际执行的结果不一定是一致的。
  4. find . -not -name ".*" 表示不找隐藏文件

以上脚本均在 centos 和 MAC 下测试通过,在其他 linux 下可能会有稍许不同。

本文由 FungLeo 原创,允许转载,但转载必须保留首发链接。

Shell 命令行,写一个自动整理 ~/Downloads/ 文件夹下文件的脚本的更多相关文章

  1. python调用另一个文件中的代码,pycharm环境下:同文件夹下文件(.py)之间的调用,出现红线问题

    如何调用另一个python文件中的代码无论我们选择用何种语言进行程序设计时,都不可能只有一个文件(除了“hello world”),通常情况下,我们都需要在一个文件中调用另外一个文件的函数呀数据等等, ...

  2. Ubuntu 统计文件夹下文件个数的命令

    查看当前目录下的文件数量(不包含子目录中的文件) ls -l|grep "^-"| wc -l 查看当前目录下的文件数量(包含子目录中的文件) 注意:R,代表子目录 ls -lR| ...

  3. [linux常用命令]查看当前文件夹或该文件夹下文件(夹)的大小

    du -sh  *(星号表示当前所有文件夹)可以查看当前目录下各个文件夹的大小,-s表示只显示当前文件夹(不加-s你可以看到所有文件夹下的子文件夹的大小,太多了),-h表示以合适的大小查看.(可以用- ...

  4. 【AMAD】watchdog -- 用于监控文件系统的事件,并且提供了shell命令行工具

    简介 动机 作用 用法 个人评分 简介 用于监控文件系统的事件的Python库,并且提供了shell命令行工具 动机 有很多情况下,我们希望监控文件的变化,在变化之后作出一些响应. 比如flask,d ...

  5. HDFS shell命令行常见操作

    hadoop学习及实践笔记—— HDFS shell命令行常见操作 附:HDFS shell guide文档地址 http://hadoop.apache.org/docs/r2.5.2/hadoop ...

  6. hadoop2.5.2学习及实践笔记(五)—— HDFS shell命令行常见操作

    附:HDFS shell guide文档地址 http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-common/FileSy ...

  7. shell命令查看某文件夹下的文件个数

    shell命令查看某文件夹下的文件个数 2010-06-25 17:05:15|  分类: shell |字号 订阅   1.查看某文件夹下文件的个数: ls -l |grep "^-&qu ...

  8. shell统计当前文件夹下的文件个数、目录个数

    1. 统计当前文件夹下文件的个数 ls -l |grep "^-"|wc -l 2. 统计当前文件夹下目录的个数 ls -l |grep "^d"|wc -l ...

  9. Shell 命令行 从日志文件中根据将符合内容的日志输出到另一个文件

    Shell 命令行 从日志文件中根据将符合内容的日志输出到另一个文件 前面我写了一篇博文Shell 从日志文件中选择时间段内的日志输出到另一个文件,利用循环实现了我想要实现的内容. 但是用这个脚本的同 ...

随机推荐

  1. React Native专题-江清清

    本React Native讲解专题:主要讲解了React Native开发,由基础环境搭建配置入门,基础,进阶相关讲解. 刚创建的React Native交流8群:533435865  欢迎各位大牛, ...

  2. tcp socket http(复制的)

    物理层-- 数据链路层-- 网络层--                       IP协议 传输层--                       TCP协议 会话层-- 表示层和应用层--     ...

  3. ZOJ Monthly, June 2018 Solution

    A - Peer Review Water. #include <bits/stdc++.h> using namespace std; int t, n; int main() { sc ...

  4. zw版【转发·台湾nvp系列Delphi例程】HALCON SetIcon1

    zw版[转发·台湾nvp系列Delphi例程]HALCON SetIcon1 procedure TForm1.Button1Click(Sender: TObject);var img : HIma ...

  5. 项目管理工具- Maven

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3. ...

  6. 文件读写网络IO简单了解,同步IO和异步IO

    在Linux中,对文件的读写其实就是IO. 与IO有关的名词:同步,异步,阻塞,非阻塞,甚至是同步阻塞,同步非阻塞,异步阻塞,异步非阻塞.别急,下面有举例IO分为两大种,同步和异步 同步IO:阻塞IO ...

  7. 20145335郝昊《网络攻防》Bof逆向基础——ShellCode注入与执行

    20145335郝昊<网络攻防>Bof逆向基础--ShellCode注入与执行 实验原理 关于ShellCode:ShellCode是一段代码,作为数据发送给受攻击服务器,是溢出程序和蠕虫 ...

  8. 20145325张梓靖 《Java程序设计》第5周学习总结

    20145325张梓靖 <Java程序设计>第5周学习总结 教材学习内容总结 try catch Java中所有错误都会被打包为对象.如果某个方法声明会抛出Throwable或子类实例,只 ...

  9. JQuery+CSS3实现Ajax加载时loading效果

    之前通过Ajax请求加载数据的时候,在数据还没有呈现出来前,为了更好的用户体验,总会弄个loading告诉用户其实内容正在加载,而不是网站崩了.但是貌似之前使用gif图片的情况比较多,可能是为了兼容各 ...

  10. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...