ソースディレクトリ内のファイルをプレフィックスに応じて異なるディレクトリに分散するためのアルゴリズム設計と C コードの実装

ソースディレクトリ内のファイルをプレフィックスに応じて異なるディレクトリに分散するためのアルゴリズム設計と C コードの実装

1. 要件の説明

Linux システムのソース ディレクトリには、同じサフィックスを持つファイルがいくつかあります。これらのファイルをプレフィックスに応じて異なるディレクトリに分散するプログラムを作成してください。

たとえば、同じサフィックスを持つ 3 つのファイル File1_1.txt、File2_1.txt、File3_1.txt がソース ディレクトリ SourceDir に保存されているとします。プレフィックス File1_、File2_、File3_ に従って、これらのファイルはそれぞれディレクトリ FileDir1、FileDir2、FileDir3 に移動 (配布) されます。

2. アルゴリズム設計

要件に基づいて、図 1 に示すプログラム フローを採​​用できます。

図1 全体的なプロセスフロー

3. 特別なプロセスに関する考慮事項

プログラムを作成する過程では、次のような特別なプロセスが考慮されます。

1. ソース ディレクトリのスキャン中にエラーが発生した場合、プログラムは次のディレクトリのスキャンを続行せずに実行を停止します。

2. 空のファイル(サイズが 0 のファイル)がある場合は、配布せずにソース ディレクトリで直接削除します。

3. ソース ディレクトリに配置されたファイルをいつでも処理できるように、プログラムはソース ディレクトリを一定の間隔 (1 分など) でスキャンします。つまり、人間による操作がなければ、プログラムは起動後継続的に実行されます。

4. プログラムコード

  1. /******************************************************************************************
  2. * 著作権 (C) 2016、Zhou Zhaoxiong。
  3. *
  4. * ファイル名: FileDistribute.c
  5. * ファイルID: なし
  6. * 内容の概要: ディレクトリ内のファイルをプレフィックスに従って対応するディレクトリに配布する
  7. * その他の指示: なし
  8. * 現在のバージョン: V1.0
  9. * 著者: 周昭雄
  10. * 完成日: 20160517
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include <文字列.h>
  15. #include <dirent.h>
  16. #include <ftw.h>
  17. #include <時間.h>
  18.  
  19. // データ型を再定義する
  20. typedef 符号付きint INT32;
  21. typedef 符号なしint UINT32;
  22. typedef unsigned char UINT8;
  23.  
  24. //グローバル変数の定義
  25. UINT8 g_szSourceDir[256] = {0}; // ソースファイルのディレクトリ
  26.  
  27. // 関数宣言
  28. INT32 SelectFlies(構造体 dirent *pDir);
  29. void スキャンディレクトリと配布(void);
  30. void スリープ(UINT32 iCountMs);
  31.  
  32.  
  33. /****************************************************************
  34. * 機能説明: 主な機能
  35. * 入力パラメータ: なし
  36. * 出力パラメータ: なし
  37. * 戻り値: 0 - 実行完了
  38. * その他の指示: なし
  39. * 変更日 バージョン番号 修正者 変更内容
  40. * -------------------------------------------------------------  
  41. * 20160517 V1.0 作成者: Zhou Zhaoxiong
  42. ************************************************************************/
  43. INT32メイン(void)
  44. {
  45. // ソースファイルのディレクトリ
  46. snprintf(g_szSourceDir, sizeof(g_szSourceDir)-1, "%s/zhouzx/TestDir/SourceDir" , getenv( "HOME" ));
  47.  
  48. //ファイル配布を実行する関数を呼び出す
  49. (1)
  50. {
  51. スキャンディレクトリと配布();
  52.  
  53. Sleep(60 * 1000); // 1分ごとにファイルを配布する
  54. }
  55.  
  56. 0を返します
  57. }
  58.  
  59.  
  60. /******************************************************************************************
  61. * 機能の説明: 拡張子に基づいてファイルを選択
  62. * 入力パラメータ: dir-ディレクトリ
  63. * 出力パラメータ: なし
  64. * 戻り値: 0-失敗、1-成功
  65. * その他の指示: test.txt のようなファイルはスキャン対象ですが、test のようなファイルは条件を満たしていません。
  66. * 変更日 バージョン番号 修正者 変更内容
  67. * --------------------------------------------------------------------  
  68. * 20160517 V1.0 作成者: ZhouZhaoxiong
  69. ******************************************************************************/
  70. INT32 SelectFlies(構造体 dirent *pDir)
  71. {
  72. (pDir == NULL )の場合
  73. {
  74. printf( "SelectFlies:入力パラメータがNULLです!\n" );
  75. 0を返します
  76. }
  77.  
  78. // .txt (サフィックス) に基づいてファイルを選択する
  79. (strstr(pDir->d_name, ".txt" ) != NULL の場合)
  80. {
  81. return 1; // 条件を満たすファイルが見つかりました
  82. }
  83. それ以外 
  84. {
  85. 0を返します
  86. }
  87. }
  88.  
  89.  
  90. /******************************************************************************************
  91. * 機能の説明: ディレクトリをスキャンしてファイルを配布する
  92. * 入力パラメータ: なし
  93. * 出力パラメータ: なし
  94. * 戻り値: なし
  95. * その他の指示: なし
  96. * 変更日 バージョン番号 修正者 変更内容
  97. * --------------------------------------------------------------------  
  98. * 20160517 V1.0 作成者: ZhouZhaoxiong
  99. ******************************************************************************/
  100. void スキャンディレクトリと配布(void)
  101. {
  102. INT32 iScanDirRet = 0;
  103. UINT32 iFileIdx = 0;
  104. UINT32 iFileCount = 0;
  105. UINT32 iFileSize = 0;
  106. UINT8 szFileDir[256] = {0};
  107. UINT8 szScanedFile[512] = {0};
  108. UINT8 szCmdBuf[256] = {0};
  109. ファイル *fp = NULL ;
  110. 構造体 dirent **ppDirEnt = NULL ;
  111.  
  112. // ソースディレクトリをスキャンしてファイルを配布する
  113. iScanDirRet = scandir(g_szSourceDir、&ppDirEnt、SelectFlies、alphasort);
  114. if (iScanDirRet < 0) // ディレクトリのスキャン中にエラーが発生しました
  115. {
  116. printf( "ScanDirAndDistribute:exec scandir に失敗しました。パス=%s\n" , g_szSourceDir);
  117. 戻る;
  118. }
  119. else if (iScanDirRet == 0) // ディレクトリにファイルがありません
  120. {
  121. printf( "ScanDirAndDistribute:ディレクトリ%sに条件に合うファイルがありません\n" , g_szSourceDir);
  122. }
  123. else // 条件を満たすファイルを対応するディレクトリに移動する
  124. {
  125. (iFileIdx = 0; iFileIdx < iScanDirRet; iFileIdx ++)の場合
  126. {
  127. // まずスキャンしたファイルが空ファイルかどうかを判断し、空ファイルの場合は直接削除し、空ファイルでない場合は移動操作を実行します
  128. memset(szScanedFile, 0x00, sizeof(szScanedFile));
  129. snprintf(szScanedFile, sizeof(szScanedFile) - 1, "%s/%s" , g_szSourceDir, ppDirEnt[iFileIdx]->d_name);
  130. fp = fopen(szScanedFile, "r" );
  131. if (fp == NULL ) // ファイルを開けなかった場合は直接戻ります
  132. {
  133. printf( "ScanDirAndDistribute:ファイル %s のオープンに失敗しました。確認してください!\n" , szScanedFile);
  134. 戻る;
  135. }
  136. fseek(fp, 0, SEEK_END);
  137. ファイルサイズ = ftell(fp);
  138. if (iFileSize == 0) // ファイルは空のファイルです
  139. {
  140. printf( "ScanDirAndDistribute:%s は空のファイルなので、直接削除してください!\n" , szScanedFile);
  141. memset(szCmdBuf, 0x00, sizeof(szCmdBuf));
  142. snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "rm %s" , szScanedFile);
  143. システム(szCmdBuf);
  144. }
  145. else // プレフィックスに従って対応するディレクトリにファイルを移動(配布)します
  146. {
  147. if (strncmp(ppDirEnt[iFileIdx]->d_name, "File1_" , strlen( "File1_" )) == 0) // FileDir1 に移動
  148. {
  149. memset(szFileDir, 0x00, sizeof(szFileDir));
  150. snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir1" , getenv( "HOME" ));
  151. }
  152. else if (strncmp(ppDirEnt[iFileIdx]->d_name, "File2_" , strlen( "File2_" )) == 0) // FileDir2 に移動する
  153. {
  154. memset(szFileDir, 0x00, sizeof(szFileDir));
  155. snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir2" , getenv( "HOME" ));
  156. }
  157. else if (strncmp(ppDirEnt[iFileIdx]->d_name, "File3_" , strlen( "File3_" )) == 0) // FileDir3 に移動
  158. {
  159. memset(szFileDir, 0x00, sizeof(szFileDir));
  160. snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir3" , getenv( "HOME" ));
  161. }
  162. else // プレフィックスが満たされていない場合は、ファイルを削除するだけです
  163. {
  164. memset(szCmdBuf, 0x00, sizeof(szCmdBuf));
  165. snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "rm %s" , szScanedFile);
  166. システム(szCmdBuf);
  167.  
  168. printf( "ScanDirAndDistribute:now, %s\n" , szCmdBuf);
  169.  
  170. continue ; //次の判定を続ける
  171. }
  172.  
  173. memset(szCmdBuf, 0x00, sizeof(szCmdBuf));
  174. snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "mv %s %s" , szScanedFile, szFileDir);
  175. システム(szCmdBuf);
  176.  
  177. printf( "ScanDirAndDistribute:now, %s\n" , szCmdBuf);
  178.  
  179. ファイルカウント++;
  180. }
  181. }
  182. }
  183.  
  184. printf( "ScanDirAndDistribute: 今回は合計 %d 個のファイルを移動しました。\n" , iFileCount);
  185.  
  186. 戻る;
  187. }
  188.  
  189.  
  190. /******************************************************************************************
  191. * 機能説明: プログラム休止状態
  192. * 入力パラメータ: iCountMs - スリープ時間 (単位: ms)
  193. * 出力パラメータ: なし
  194. * 戻り値: なし
  195. * その他の指示: なし
  196. * 変更日 バージョン番号 修正者 変更内容
  197. * ------------------------------------------------------------------  
  198. * 20160517 V1.0 作成者: Zhou Zhaoxiong
  199. ****************************************************************************/
  200. void スリープ(UINT32 iCountMs)
  201. {
  202. 構造体timeval t_timeout = {0};
  203.  
  204. (iCountMs < 1000)の場合
  205. {
  206. t_timeout.tv_sec = 0;
  207. t_timeout.tv_usec = iCountMs * 1000;
  208. }
  209. それ以外 
  210. {
  211. t_timeout.tv_sec = iCountMs / 1000;
  212. t_timeout.tv_usec = (iCountMs % 1000) * 1000;
  213. }
  214. select (0, NULL , NULL , NULL , &t_timeout); // select関数を呼び出してプログラムをブロックする
  215. }

5. プログラムのテスト

作成したプログラム「FileDistribute.c」を Linux マシンにアップロードし、「gcc -g -o FileDistribute FileDistribute.c」コマンドを使用してプログラムをコンパイルし、「FileDistribute」ファイルを生成します。以下はプログラムの詳細なテストです。

1. プログラムを起動する前に、File1_1.txt、File2_1.txt、File3_1.txt をソース ディレクトリ SourceDir に配置します。プログラムは次のように実行されます。

  1. ScanDirAndDistribute:今、mv /home/zhou/zhouzx/TestDir/SourceDir/File1_1.txt /home/zhou/zhouzx/TestDir/FileDir1
  2. ScanDirAndDistribute:now、mv /home/zhou/zhouzx/TestDir/SourceDir/File2_1.txt /home/zhou/zhouzx/TestDir/FileDir2
  3. ScanDirAndDistribute:now、mv /home/zhou/zhouzx/TestDir/SourceDir/File3_1.txt /home/zhou/zhouzx/TestDir/FileDir3
  4. ScanDirAndDistribute:今回は合計 3 つのファイルを移動しました。

ご覧のとおり、ソース ディレクトリ内の 3 つのファイルは存在しなくなりました。これらは、それぞれ結果ディレクトリ FileDir1、FileDir2、FileDir3 に移動されました。

  1. ~/zhouzx/TestDir/SourceDir>ll
  2. 合計 0
  3.  
  4. ~/zhouzx/TestDir/FileDir1>ll
  5. -rw ------- 1 zhou ユーザー 12 2016-05-17 18:58 File1_1.txt  
  6.  
  7. ~/zhouzx/TestDir/FileDir2>ll
  8. -rw ------- 1 zhou ユーザー 12 2016-05-17 18:58 File2_1.txt  
  9.  
  10. ~/zhouzx/TestDir/FileDir3>ll
  11. -rw ------- 1 zhou ユーザー 12 2016-05-17 18:58 File3_1.txt  

2. しばらくしてから、File4_1.txt ファイルをソース ディレクトリ SourceDir に置くと、プログラムは次のように実行されます。

  1. ScanDirAndDistribute:今、rm /home/zhou/zhouzx/TestDir/SourceDir/File4_1.txt
  2. ScanDirAndDistribute:今回は合計 0 個のファイルを移動しました。1212

プレフィックスが一致しなかったため、File4_1.txt ファイルが直接削除されたことがわかります。

  1. ~/zhouzx/TestDir/SourceDir>ll  
  2. 合計 01212

3. しばらくしてから、空のファイル File_7.txt、File_8.txt、File_9.txt をソース ディレクトリ SourceDir に配置すると、プログラムは次のように実行されます。

  1. ScanDirAndDistribute:/home/zhou/zhouzx/TestDir/SourceDir/File_7.txt空のファイルので、直接削除してください
  2. ScanDirAndDistribute:/home/zhou/zhouzx/TestDir/SourceDir/File_8.txt は空のファイルので、直接削除してください
  3. ScanDirAndDistribute:/home/zhou/zhouzx/TestDir/SourceDir/File_9.txt は空のファイルので、直接削除してください
  4. ScanDirAndDistribute:今回は合計 0 個のファイルを移動しました。

ソースディレクトリ SourceDir 内のすべての空のファイルが削除されたことがわかります。

  1. ~/zhouzx/TestDir/SourceDir>ll  
  2. 合計 01212

6. 需要拡大

この記事の要件と手順に基づいて、要件に対する次の拡張を検討できます。

1. ファイルを移動 (配布) する前に、まず対応する結果ディレクトリに同じファイル名のファイルが存在するかどうかを確認します。存在する場合は、ソース ディレクトリ内のファイルを直接削除します。存在しない場合は、ファイルを対応する結果ディレクトリに移動します。

2. 結果ディレクトリ内のファイルが多すぎるのを避けるために、プログラムにクリーンアップ メカニズムを追加して、一定期間以上保存されているファイルを削除することができます。

3. プログラムの柔軟性を反映するために、一部のファイル情報(ファイルのプレフィックス、サフィックス、保存ディレクトリ、スキャン間隔など)を設定ファイルに保存できます。プログラムが起動すると、関連する設定項目の値が読み取られ、後続のディレクトリスキャンとファイル配布操作が実行されます。

[この記事は51CTOコラムニストの周兆雄氏によるオリジナル記事です。著者のWeChat公開アカウント:周の論理(logiczhou)]

この著者の他の記事を読むにはここをクリックしてください

<<:  同じプレフィックスとサフィックスを持つファイルを同じディレクトリに移動するためのアルゴリズム設計と C コードの実装

>>:  機械学習は科学プロジェクトからビジネスプランまで3段階の戦略を完了します

ブログ    
ブログ    
ブログ    

推薦する

求人検索サイトIndeedの統計:AI採用は減速、求職者の関心は低下

6月末、わが国各省市で大学入試結果が次々と発表される中、学生の専攻選択は統計的な傾向に新たな波を起こ...

自動運転車が「すべての人を助ける」ことができるようになるには、15の課題を乗り越える必要がある

[[251351]]自動運転車の将来は、交通手段に革命を起こすと予測されていた電動スクーターの歴史と...

NLP: 車輪の再発明はしない

導入自然言語処理 (NLP) は困難な分野です。構造化されていないテキストから有用な結論を生成するこ...

...

Google Chat GPT は、メールを読んだり、予定をスケジュールしたり、フライトやホテルをワンクリックで予約したりできます。

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

機械学習とデータサイエンスに関するこれらの 10 冊の無料書籍を読みたくないですか?

機械学習とデータサイエンスに関する新しい本を本棚に追加する時期が来ました。KDnuggets 編集者...

脳の治癒、人間と機械の共生、マスク氏は「脳コンピューターインターフェース」を擁護

[[316164]]天才イーロン・マスクについて語るとき、多くの人はまずテスラを思い浮かべるでしょう...

仮病を使って休暇を取る時代は終わり?イスラエルの企業が、45秒で病気を装う従業員を識別できるAIプログラムを開発

海外で流行が猛威を振るう中、多くの企業は従業員にリモートワークをさせざるを得ない状況となっている。そ...

Alibabaオープンソース!軽量ディープラーニングエッジ推論エンジンMNN

最近、アリババは軽量ディープラーニングエッジ推論エンジン「MNN」を正式にオープンソース化しました。...

施設管理の未来: 2024 年までの業界動向

2024 年に向けて、業界では建物の管理と保守の方法に影響を与えるいくつかの刺激的な変化が起こるでし...

例を見ればそれが分かります! MAXHUBはCOFCOとGuoqiaoyuanの小売業変革を支援します

小売業界の新小売への変革は、業界ではすでに認識されているトレンドであり、真に実装されたインテリジェン...

...

ビッグデータ分析と人工知能:技術コンテンツの価値分析

[[265480]]テクノロジーの継続的な発展に伴い、テクノロジーの種類はますます増えています。人々...

ネットワークにおける機械学習の実用的応用

各 Web アプリケーションには独自の機能とパフォーマンス パラメーターのセットがあり、これらは動的...

AI + スマート交通が全体のアップグレードと調整を実現

[[353150]]人工知能は、人間のように知覚、認識、決定、実行できる人工プログラムまたはシステム...